aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZoltan Herczeg <zherczeg.u-szeged@partner.samsung.com>2021-10-07 11:35:49 +0200
committerGitHub <noreply@github.com>2021-10-07 11:35:49 +0200
commitc696bc9327c0dd79264a3c73b61483c705197d51 (patch)
tree0c9bc5e65f065b99b6c3bf0e492da7b4ec0f9d4a
parent7c21fb89b272e9e9f6fbd9804f4356b59a4a2c9c (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.md291
-rw-r--r--jerry-core/api/jerry.c94
-rw-r--r--jerry-core/ecma/base/ecma-globals.h26
-rw-r--r--jerry-core/ecma/base/ecma-helpers.c46
-rw-r--r--jerry-core/ecma/base/ecma-helpers.h2
-rw-r--r--jerry-core/include/jerryscript-core.h4
-rw-r--r--tests/unit-core/test-vm-throw.c46
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 */