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:
Zoltan Herczeg
2021-10-07 11:35:49 +02:00
committed by GitHub
parent 7c21fb89b2
commit c696bc9327
7 changed files with 393 additions and 118 deletions
+75 -19
View File
@@ -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.
+14 -14
View File
@@ -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.
*/
+36 -10
View File
@@ -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)
{
+1 -1
View File
@@ -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);
+3 -1
View File
@@ -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);