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
This commit is contained in:
+222
-69
@@ -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**
|
||||
|
||||
+75
-19
@@ -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 */
|
||||
|
||||
/**
|
||||
@@ -2049,6 +2049,78 @@ jerry_set_error_object_created_callback (jerry_error_object_created_callback_t c
|
||||
JERRY_CONTEXT (error_object_created_callback_user_p) = user_p;
|
||||
} /* 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.
|
||||
*
|
||||
@@ -5288,22 +5360,6 @@ jerry_set_vm_exec_stop_callback (jerry_vm_exec_stop_callback_t stop_cb, /**< per
|
||||
#endif /* JERRY_VM_EXEC_STOP */
|
||||
} /* 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.
|
||||
|
||||
@@ -1938,17 +1938,22 @@ typedef struct
|
||||
ecma_stringbuilder_header_t *header_p; /**< pointer to header */
|
||||
} ecma_stringbuilder_t;
|
||||
|
||||
/**
|
||||
* Types for extended primitive values.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
#ifndef JERRY_BUILTIN_BIGINT
|
||||
ECMA_EXTENDED_PRIMITIVE_BIGINT, /**< BigInt value */
|
||||
/**
|
||||
* BigInt type.
|
||||
*/
|
||||
#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.
|
||||
@@ -1963,11 +1968,6 @@ typedef struct
|
||||
} u;
|
||||
} 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.
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
|
||||
jcontext_set_exception_flag (true);
|
||||
jcontext_set_abort_flag (ECMA_EXTENDED_PRIMITIVE_GET_TYPE (error_ref_p) == ECMA_EXTENDED_PRIMITIVE_ABORT);
|
||||
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 */
|
||||
|
||||
JERRY_CONTEXT (status_flags) = status_flags;
|
||||
|
||||
if (error_ref_p->refs_and_type >= 2 * ECMA_EXTENDED_PRIMITIVE_REF_ONE)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
@@ -175,25 +195,43 @@ main (void)
|
||||
|
||||
mode = 5;
|
||||
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 */
|
||||
|
||||
Reference in New Issue
Block a user