diff options
author | Zoltan Herczeg <zherczeg.u-szeged@partner.samsung.com> | 2021-10-07 11:35:49 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-07 11:35:49 +0200 |
commit | c696bc9327c0dd79264a3c73b61483c705197d51 (patch) | |
tree | 0c9bc5e65f065b99b6c3bf0e492da7b4ec0f9d4a | |
parent | 7c21fb89b272e9e9f6fbd9804f4356b59a4a2c9c (diff) |
Implement vm throw capture status management for API errors (#4783)
JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
-rw-r--r-- | docs/02.API-REFERENCE.md | 291 | ||||
-rw-r--r-- | jerry-core/api/jerry.c | 94 | ||||
-rw-r--r-- | jerry-core/ecma/base/ecma-globals.h | 26 | ||||
-rw-r--r-- | jerry-core/ecma/base/ecma-helpers.c | 46 | ||||
-rw-r--r-- | jerry-core/ecma/base/ecma-helpers.h | 2 | ||||
-rw-r--r-- | jerry-core/include/jerryscript-core.h | 4 | ||||
-rw-r--r-- | tests/unit-core/test-vm-throw.c | 46 |
7 files changed, 392 insertions, 117 deletions
diff --git a/docs/02.API-REFERENCE.md b/docs/02.API-REFERENCE.md index b3bb9fe9..0b0db323 100644 --- a/docs/02.API-REFERENCE.md +++ b/docs/02.API-REFERENCE.md @@ -3862,6 +3862,228 @@ void main(void) - [jerry_error_object_created_callback_t](#jerry_error_object_created_callback_t) +## jerry_set_vm_throw_callback + +**Summary** + +The callback passed to this function is called when an error is thrown +in ECMAScript code. The callback is not called again until the value is +caught. See: [jerry_vm_throw_callback_t](#jerry_vm_throw_callback_t). + +*Notes*: +- This API depends on a build option (`JERRY_VM_THROW`) and can be checked + in runtime with the `JERRY_FEATURE_VM_THROW` feature enum value, + see: [jerry_is_feature_enabled](#jerry_is_feature_enabled). + +**Prototype** + +```c +void +jerry_set_vm_throw_callback (jerry_vm_throw_callback_t throw_cb, + void *user_p); +``` + +- `throw_cb` - callback which is called on throws (passing NULL disables this feature) +- `user_p` - user pointer passed to the `throw_cb` function + +*New in version [[NEXT_RELEASE]]*. + +**Example** + +[doctest]: # (test="compile") + +```c +#include "jerryscript.h" + +static void +vm_throw_callback (const jerry_value_t error_value, /**< captured error */ + void *user_p) /**< user pointer */ +{ + (void) error_value; + + /* Counts the number of throws. */ + int *counter_p = (int *) user_p; + (*counter_p)++; +} + +int +main (void) +{ + jerry_init (JERRY_INIT_EMPTY); + + int counter = 0; + jerry_set_vm_throw_callback (vm_throw_callback, &counter); + + const jerry_char_t script[] = "try { throw new Error('1') } catch (e) { throw new Error('2') }"; + + jerry_release_value (jerry_eval (script, sizeof (script) - 1, JERRY_PARSE_NO_OPTS)); + + /* The counter contains 2. */ + + jerry_cleanup (); + return 0; +} +``` + +**See also** + +- [jerry_vm_throw_callback_t](#jerry_vm_throw_callback_t) +- [jerry_error_is_throw_captured](#jerry_error_is_throw_captured) +- [jerry_error_set_throw_capture](#jerry_error_set_throw_capture) + +## jerry_error_is_throw_captured + +**Summary** + +Checks whether the callback set by [jerry_set_vm_throw_callback](#jerry_set_vm_throw_callback) +captured the error. + +*Notes*: +- This API depends on a build option (`JERRY_VM_THROW`) and can be checked + in runtime with the `JERRY_FEATURE_VM_THROW` feature enum value, + see: [jerry_is_feature_enabled](#jerry_is_feature_enabled). + +**Prototype** + +```c +bool jerry_error_is_throw_captured (jerry_value_t value); +``` + +- `value` - api value (should be an error reference) +- return value + - true, if the vm throw callback captured the error + - false, otherwise + +*New in version [[NEXT_RELEASE]]*. + +**Example** + +[doctest]: # (test="compile") + +```c +#include "jerryscript.h" + +static void +vm_throw_callback (const jerry_value_t error_value, /**< captured error */ + void *user_p) /**< user pointer */ +{ + (void) error_value; + (void) user_p; +} + +int +main (void) +{ + jerry_init (JERRY_INIT_EMPTY); + + int counter = 0; + jerry_set_vm_throw_callback (vm_throw_callback, &counter); + + const jerry_char_t script[] = "throw new Error()"; + jerry_value_t result_value = jerry_eval (script, sizeof (script) - 1, JERRY_PARSE_NO_OPTS); + + if (jerry_error_is_throw_captured (result_value)) + { + /* Code enters here, because the vm_throw_callback function is called. */ + } + + jerry_release_value (result_value); + + jerry_cleanup (); + return 0; +} +``` + +**See also** + +- [jerry_set_vm_throw_callback](#jerry_set_vm_throw_callback) +- [jerry_error_set_throw_capture](#jerry_error_set_throw_capture) + +## jerry_error_set_throw_capture + +**Summary** + +Sets whether the callback set by [jerry_set_vm_throw_callback](#jerry_set_vm_throw_callback) +should capture the error or not. + +*Notes*: +- This API depends on a build option (`JERRY_VM_THROW`) and can be checked + in runtime with the `JERRY_FEATURE_VM_THROW` feature enum value, + see: [jerry_is_feature_enabled](#jerry_is_feature_enabled). + +**Prototype** + +```c +void jerry_error_set_throw_capture (jerry_value_t value, bool should_capture); +``` + +- `value` - api value (should be an error reference) +- `should_capture` - callback should capture this error + +*New in version [[NEXT_RELEASE]]*. + +**Example** + +[doctest]: # (test="compile") + +```c +#include "jerryscript.h" + +static void +vm_throw_callback (const jerry_value_t error_value, /**< captured error */ + void *user_p) /**< user pointer */ +{ + (void) error_value; + (void) user_p; +} + +static jerry_value_t +throw_exception (const jerry_call_info_t *call_info_p, /**< call info */ + const jerry_value_t argv[], /**< argument list */ + const jerry_length_t argc) /**< argument count */ +{ + (void) call_info_p; + (void) argv; + (void) argc; + + jerry_value_t result_value = jerry_create_error (JERRY_ERROR_COMMON, (const jerry_char_t *) "Error!"); + + /* Ignore calling the vm_throw_callback function. */ + jerry_error_set_throw_capture (result_value, false); + return result_value; +} + +int +main (void) +{ + jerry_init (JERRY_INIT_EMPTY); + + int counter = 0; + jerry_set_vm_throw_callback (vm_throw_callback, &counter); + + jerry_value_t global_object_value = jerry_get_global_object (); + jerry_value_t function_value = jerry_create_external_function (throw_exception); + jerry_value_t function_name_value = jerry_create_string ((const jerry_char_t *) "throw_exception"); + + jerry_release_value (jerry_set_property (global_object_value, function_name_value, function_value)); + jerry_release_value (function_name_value); + jerry_release_value (function_value); + jerry_release_value (global_object_value); + + const jerry_char_t script[] = "throw_exception()"; + jerry_release_value (jerry_eval (script, sizeof (script) - 1, JERRY_PARSE_NO_OPTS)); + + jerry_cleanup (); + return 0; +} +``` + +**See also** + +- [jerry_set_vm_throw_callback](#jerry_set_vm_throw_callback) +- [jerry_error_is_throw_captured](#jerry_error_is_throw_captured) + + # Getter functions of 'jerry_value_t' Get raw data from API values. @@ -11680,75 +11902,6 @@ main (void) - [jerry_vm_exec_stop_callback_t](#jerry_vm_exec_stop_callback_t) -## jerry_set_vm_throw_callback - -**Summary** - -The callback passed to this function is called when an error is thrown -in ECMAScript code. The callback is not called again until the value is -caught. See: [jerry_vm_throw_callback_t](#jerry_vm_throw_callback_t). - -*Notes*: -- This API depends on a build option (`JERRY_VM_THROW`) and can be checked - in runtime with the `JERRY_FEATURE_VM_THROW` feature enum value, - see: [jerry_is_feature_enabled](#jerry_is_feature_enabled). - -**Prototype** - -```c -void -jerry_set_vm_throw_callback (jerry_vm_throw_callback_t throw_cb, - void *user_p); -``` - -- `throw_cb` - callback which is called on throws (passing NULL disables this feature) -- `user_p` - user pointer passed to the `throw_cb` function - -*New in version [[NEXT_RELEASE]]*. - -**Example** - -[doctest]: # (test="compile") - -```c -#include "jerryscript.h" - -static void -vm_throw_callback (const jerry_value_t error_value, /**< captured error */ - void *user_p) /**< user pointer */ -{ - (void) error_value; - - /* Counts the number of throws. */ - int *counter_p = (int *) user_p; - (*counter_p)++; -} - -int -main (void) -{ - jerry_init (JERRY_INIT_EMPTY); - - int counter = 0; - jerry_set_vm_throw_callback (vm_throw_callback, &counter); - - const jerry_char_t script[] = "try { throw new Error('1') } catch (e) { throw new Error('2') }"; - - jerry_value_t parsed_code = jerry_parse (script, sizeof (script) - 1, NULL); - jerry_release_value (jerry_run (parsed_code)); - jerry_release_value (parsed_code); - - /* The counter contains 2. */ - - jerry_cleanup (); - return 0; -} -``` - -**See also** - -- [jerry_vm_throw_callback_t](#jerry_vm_throw_callback_t) - ## jerry_get_resource_name **Summary** diff --git a/jerry-core/api/jerry.c b/jerry-core/api/jerry.c index 3a3c39a3..37043a34 100644 --- a/jerry-core/api/jerry.c +++ b/jerry-core/api/jerry.c @@ -1163,7 +1163,7 @@ jerry_value_is_abort (const jerry_value_t value) /**< api value */ ecma_extended_primitive_t *error_ref_p = ecma_get_extended_primitive_from_value (value); - return ECMA_EXTENDED_PRIMITIVE_GET_TYPE (error_ref_p) == ECMA_EXTENDED_PRIMITIVE_ABORT; + return (error_ref_p->refs_and_type & ECMA_ERROR_API_ABORT) != 0; } /* jerry_value_is_abort */ /** @@ -1966,7 +1966,7 @@ jerry_create_abort_from_value (jerry_value_t value, /**< api value */ value = ecma_copy_value (value); } - return ecma_create_error_reference (value, false); + return ecma_create_error_reference (value, ECMA_ERROR_API_ABORT); } /* jerry_create_abort_from_value */ /** @@ -2001,7 +2001,7 @@ jerry_create_error_from_value (jerry_value_t value, /**< api value */ value = ecma_copy_value (value); } - return ecma_create_error_reference (value, true); + return ecma_create_error_reference (value, 0); } /* jerry_create_error_from_value */ /** @@ -2050,6 +2050,78 @@ jerry_set_error_object_created_callback (jerry_error_object_created_callback_t c } /* jerry_set_error_object_created_callback */ /** + * When JERRY_VM_THROW is enabled, the callback passed to this + * function is called when an error is thrown in ECMAScript code. + */ +void jerry_set_vm_throw_callback (jerry_vm_throw_callback_t throw_cb, /**< callback which is called on throws */ + void *user_p) /**< pointer passed to the function */ +{ +#if JERRY_VM_THROW + JERRY_CONTEXT (vm_throw_callback_p) = throw_cb; + JERRY_CONTEXT (vm_throw_callback_user_p) = user_p; +#else /* !JERRY_VM_THROW */ + JERRY_UNUSED (throw_cb); + JERRY_UNUSED (user_p); +#endif /* JERRY_VM_THROW */ +} /* jerry_set_vm_throw_callback */ + +/** + * Checks whether the callback set by jerry_set_vm_throw_callback captured the error + * + * @return true, if the vm throw callback captured the error + * false, otherwise + */ +bool +jerry_error_is_throw_captured (jerry_value_t value) /**< api value */ +{ + jerry_assert_api_available (); + +#if JERRY_VM_THROW + if (!ecma_is_value_error_reference (value)) + { + return false; + } + + ecma_extended_primitive_t *error_ref_p = ecma_get_extended_primitive_from_value (value); + + return (error_ref_p->refs_and_type & ECMA_ERROR_API_THROW_CAPTURED) != 0; +#else /* !JERRY_VM_THROW */ + JERRY_UNUSED (value); + return false; +#endif /* JERRY_VM_THROW */ +} /* jerry_error_is_throw_captured */ + +/** + * Sets whether the callback set by jerry_set_vm_throw_callback should capture the error or not + */ +void +jerry_error_set_throw_capture (jerry_value_t value, /**< api value */ + bool should_capture) /**< callback should capture this error */ +{ + jerry_assert_api_available (); + +#if JERRY_VM_THROW + if (!ecma_is_value_error_reference (value)) + { + return; + } + + ecma_extended_primitive_t *error_ref_p = ecma_get_extended_primitive_from_value (value); + + if (should_capture) + { + error_ref_p->refs_and_type &= ~(uint32_t) ECMA_ERROR_API_THROW_CAPTURED; + return; + } + + error_ref_p->refs_and_type |= ECMA_ERROR_API_THROW_CAPTURED; +#else /* !JERRY_VM_THROW */ + JERRY_UNUSED (value); + JERRY_UNUSED (should_capture); +#endif /* JERRY_VM_THROW */ +} /* jerry_error_set_throw_capture */ + +/** * Return the type of the Error object if possible. * * @return one of the jerry_error_t value as the type of the Error object @@ -5289,22 +5361,6 @@ jerry_set_vm_exec_stop_callback (jerry_vm_exec_stop_callback_t stop_cb, /**< per } /* jerry_set_vm_exec_stop_callback */ /** - * When JERRY_VM_THROW is enabled, the callback passed to this - * function is called when an error is thrown in ECMAScript code. - */ -void jerry_set_vm_throw_callback (jerry_vm_throw_callback_t throw_cb, /**< callback which is called on throws */ - void *user_p) /**< pointer passed to the function */ -{ -#if JERRY_VM_THROW - JERRY_CONTEXT (vm_throw_callback_p) = throw_cb; - JERRY_CONTEXT (vm_throw_callback_user_p) = user_p; -#else /* !JERRY_VM_THROW */ - JERRY_UNUSED (throw_cb); - JERRY_UNUSED (user_p); -#endif /* JERRY_VM_THROW */ -} /* jerry_set_vm_throw_callback */ - -/** * Get backtrace. The backtrace is an array of strings where * each string contains the position of the corresponding frame. * The array length is zero if the backtrace is not available. diff --git a/jerry-core/ecma/base/ecma-globals.h b/jerry-core/ecma/base/ecma-globals.h index cac25be7..117049e9 100644 --- a/jerry-core/ecma/base/ecma-globals.h +++ b/jerry-core/ecma/base/ecma-globals.h @@ -1938,17 +1938,22 @@ typedef struct ecma_stringbuilder_header_t *header_p; /**< pointer to header */ } ecma_stringbuilder_t; +#ifndef JERRY_BUILTIN_BIGINT /** - * Types for extended primitive values. + * BigInt type. */ -typedef enum -{ -#ifndef JERRY_BUILTIN_BIGINT - ECMA_EXTENDED_PRIMITIVE_BIGINT, /**< BigInt value */ +#define ECMA_EXTENDED_PRIMITIVE_BIGINT 0 #endif /* !defined (JERRY_BUILTIN_BIGINT) */ - ECMA_EXTENDED_PRIMITIVE_ERROR, /**< external API error reference */ - ECMA_EXTENDED_PRIMITIVE_ABORT, /**< external API abort reference */ -} ecma_extended_primitive_type_t; + +/** + * Abort flag for errors in C API. + */ +#define ECMA_ERROR_API_ABORT (1u << 0) + +/** + * Throw captured flag for errors in C API. + */ +#define ECMA_ERROR_API_THROW_CAPTURED (1u << 1) /** * Representation of a thrown value on API level. @@ -1964,11 +1969,6 @@ typedef struct } ecma_extended_primitive_t; /** - * Get the type of an extended primitve value. - */ -#define ECMA_EXTENDED_PRIMITIVE_GET_TYPE(primitve_p) ((primitve_p)->refs_and_type & 0x7) - -/** * Value for increasing or decreasing the reference counter. */ #define ECMA_EXTENDED_PRIMITIVE_REF_ONE (1u << 3) diff --git a/jerry-core/ecma/base/ecma-helpers.c b/jerry-core/ecma/base/ecma-helpers.c index ea43fd3a..efa1a112 100644 --- a/jerry-core/ecma/base/ecma-helpers.c +++ b/jerry-core/ecma/base/ecma-helpers.c @@ -1333,13 +1333,12 @@ ecma_deref_bigint (ecma_extended_primitive_t *bigint_p) /**< bigint value */ */ ecma_value_t ecma_create_error_reference (ecma_value_t value, /**< referenced value */ - bool is_exception) /**< error reference is an exception */ + uint32_t options) /**< ECMA_ERROR_API_* options */ { ecma_extended_primitive_t *error_ref_p; error_ref_p = (ecma_extended_primitive_t *) jmem_pools_alloc (sizeof (ecma_extended_primitive_t)); - error_ref_p->refs_and_type = (ECMA_EXTENDED_PRIMITIVE_REF_ONE - | (is_exception ? ECMA_EXTENDED_PRIMITIVE_ERROR : ECMA_EXTENDED_PRIMITIVE_ABORT)); + error_ref_p->refs_and_type = ECMA_EXTENDED_PRIMITIVE_REF_ONE | options; error_ref_p->u.value = value; return ecma_make_extended_primitive_value (error_ref_p, ECMA_TYPE_ERROR); } /* ecma_create_error_reference */ @@ -1352,13 +1351,22 @@ ecma_create_error_reference (ecma_value_t value, /**< referenced value */ ecma_value_t ecma_create_error_reference_from_context (void) { - bool is_abort = jcontext_has_pending_abort (); + uint32_t options = 0; + uint32_t status_flags = JERRY_CONTEXT (status_flags); - if (is_abort) + if (status_flags & ECMA_STATUS_ABORT) { - jcontext_set_abort_flag (false); + options |= ECMA_ERROR_API_ABORT; } - return ecma_create_error_reference (jcontext_take_exception (), !is_abort); + +#if JERRY_VM_THROW + if (status_flags & ECMA_STATUS_ERROR_THROWN) + { + options |= ECMA_ERROR_API_THROW_CAPTURED; + } +#endif /* JERRY_VM_THROW */ + + return ecma_create_error_reference (jcontext_take_exception (), options); } /* ecma_create_error_reference_from_context */ /** @@ -1372,7 +1380,7 @@ ecma_create_error_reference_from_context (void) extern inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE ecma_create_error_object_reference (ecma_object_t *object_p) /**< referenced object */ { - return ecma_create_error_reference (ecma_make_object_value (object_p), true); + return ecma_create_error_reference (ecma_make_object_value (object_p), 0); } /* ecma_create_error_object_reference */ /** @@ -1389,9 +1397,27 @@ ecma_raise_error_from_error_reference (ecma_value_t value) /**< error reference JERRY_ASSERT (error_ref_p->refs_and_type >= ECMA_EXTENDED_PRIMITIVE_REF_ONE); ecma_value_t referenced_value = error_ref_p->u.value; + uint32_t status_flags = JERRY_CONTEXT (status_flags); + + status_flags |= (ECMA_STATUS_EXCEPTION +#if JERRY_VM_THROW + | ECMA_STATUS_ERROR_THROWN +#endif /* JERRY_VM_THROW */ + | ECMA_STATUS_ABORT); + + if (!(error_ref_p->refs_and_type & ECMA_ERROR_API_ABORT)) + { + status_flags &= ~(uint32_t) ECMA_STATUS_ABORT; + } + +#if JERRY_VM_THROW + if (!(error_ref_p->refs_and_type & ECMA_ERROR_API_THROW_CAPTURED)) + { + status_flags &= ~(uint32_t) ECMA_STATUS_ERROR_THROWN; + } +#endif /* JERRY_VM_THROW */ - jcontext_set_exception_flag (true); - jcontext_set_abort_flag (ECMA_EXTENDED_PRIMITIVE_GET_TYPE (error_ref_p) == ECMA_EXTENDED_PRIMITIVE_ABORT); + JERRY_CONTEXT (status_flags) = status_flags; if (error_ref_p->refs_and_type >= 2 * ECMA_EXTENDED_PRIMITIVE_REF_ONE) { diff --git a/jerry-core/ecma/base/ecma-helpers.h b/jerry-core/ecma/base/ecma-helpers.h index 2a787f1b..f96d1e00 100644 --- a/jerry-core/ecma/base/ecma-helpers.h +++ b/jerry-core/ecma/base/ecma-helpers.h @@ -526,7 +526,7 @@ void ecma_deref_error_reference (ecma_extended_primitive_t *error_ref_p); void ecma_deref_bigint (ecma_extended_primitive_t *bigint_p); #endif /* JERRY_BUILTIN_BIGINT */ -ecma_value_t ecma_create_error_reference (ecma_value_t value, bool is_exception); +ecma_value_t ecma_create_error_reference (ecma_value_t value, uint32_t options); ecma_value_t ecma_create_error_reference_from_context (void); ecma_value_t ecma_create_error_object_reference (ecma_object_t *object_p); void ecma_raise_error_from_error_reference (ecma_value_t value); diff --git a/jerry-core/include/jerryscript-core.h b/jerry-core/include/jerryscript-core.h index 38e43f29..0a4393e0 100644 --- a/jerry-core/include/jerryscript-core.h +++ b/jerry-core/include/jerryscript-core.h @@ -103,6 +103,9 @@ jerry_value_t jerry_create_abort_from_value (jerry_value_t value, bool release); jerry_value_t jerry_create_error_from_value (jerry_value_t value, bool release); jerry_value_t jerry_get_value_from_error (jerry_value_t value, bool release); void jerry_set_error_object_created_callback (jerry_error_object_created_callback_t callback, void *user_p); +void jerry_set_vm_throw_callback (jerry_vm_throw_callback_t throw_cb, void *user_p); +bool jerry_error_is_throw_captured (jerry_value_t value); +void jerry_error_set_throw_capture (jerry_value_t value, bool should_capture); /** * Error object function(s). @@ -359,7 +362,6 @@ bool jerry_backtrace_is_strict (jerry_backtrace_frame_t *frame_p); * Miscellaneous functions. */ void jerry_set_vm_exec_stop_callback (jerry_vm_exec_stop_callback_t stop_cb, void *user_p, uint32_t frequency); -void jerry_set_vm_throw_callback (jerry_vm_throw_callback_t throw_cb, void *user_p); jerry_value_t jerry_get_resource_name (const jerry_value_t value); jerry_value_t jerry_get_user_value (const jerry_value_t value); jerry_source_info_t *jerry_get_source_info (const jerry_value_t value); diff --git a/tests/unit-core/test-vm-throw.c b/tests/unit-core/test-vm-throw.c index 6eb50ccc..dd781b62 100644 --- a/tests/unit-core/test-vm-throw.c +++ b/tests/unit-core/test-vm-throw.c @@ -73,6 +73,7 @@ vm_throw_callback (const jerry_value_t error_value, /**< captured error */ break; } case 5: + case 6: { TEST_ASSERT (counter >= 1 && counter <= 2); TEST_ASSERT (jerry_value_is_false (error_value)); @@ -80,7 +81,7 @@ vm_throw_callback (const jerry_value_t error_value, /**< captured error */ } default: { - TEST_ASSERT (mode == 6 || mode == 7); + TEST_ASSERT (mode == 8 || mode == 9); TEST_ASSERT (counter == 1); TEST_ASSERT (jerry_value_is_true (error_value)); break; @@ -97,8 +98,27 @@ native_handler (const jerry_call_info_t *call_info_p, /**< call info */ (void) args_p; TEST_ASSERT (args_count == 0); + if (mode == 7) + { + jerry_value_t result = jerry_create_error (JERRY_ERROR_COMMON, (const jerry_char_t *) "Error!"); + + TEST_ASSERT (!jerry_error_is_throw_captured (result)); + jerry_error_set_throw_capture (result, false); + TEST_ASSERT (jerry_error_is_throw_captured (result)); + return result; + } + jerry_char_t source[] = TEST_STRING_LITERAL ("throw false"); - return jerry_eval (source, sizeof (source) - 1, JERRY_PARSE_NO_OPTS); + jerry_value_t result = jerry_eval (source, sizeof (source) - 1, JERRY_PARSE_NO_OPTS); + + TEST_ASSERT (jerry_error_is_throw_captured (result)); + + if (mode == 6) + { + jerry_error_set_throw_capture (result, true); + TEST_ASSERT (!jerry_error_is_throw_captured (result)); + } + return result; } /* native_handler */ static void @@ -177,23 +197,41 @@ main (void) counter = 0; do_eval (TEST_STRING_LITERAL ("native()\n"), true); + TEST_ASSERT (counter == 1); + + mode = 6; + counter = 0; + do_eval (TEST_STRING_LITERAL ("native()\n"), + true); TEST_ASSERT (counter == 2); + mode = 7; + counter = 0; + do_eval (TEST_STRING_LITERAL ("native()\n"), + true); + TEST_ASSERT (counter == 0); + /* Built-in functions should not trigger the call twice: */ - mode = 6; + mode = 8; counter = 0; do_eval (TEST_STRING_LITERAL ("function f() { eval('eval(\\'throw true\\')') }\n" "f()\n"), true); TEST_ASSERT (counter == 1); - mode = 7; + mode = 9; counter = 0; do_eval (TEST_STRING_LITERAL ("function f() { [1].map(function() { throw true }) }\n" "f()\n"), true); TEST_ASSERT (counter == 1); + jerry_value_t value = jerry_create_object (); + TEST_ASSERT (!jerry_error_is_throw_captured (value)); + jerry_error_set_throw_capture (value, false); + TEST_ASSERT (!jerry_error_is_throw_captured (value)); + jerry_release_value (value); + jerry_cleanup (); return 0; } /* main */ |