From 823a8b128d4c5424b7462ec10b810b6b126c1e12 Mon Sep 17 00:00:00 2001 From: Zoltan Herczeg Date: Tue, 27 Apr 2021 09:42:20 +0200 Subject: [PATCH] Fix error throw in jerry_define_own_property (#4662) JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com --- docs/02.API-REFERENCE.md | 15 +++------ jerry-core/api/jerry.c | 46 +++++++++++++++----------- jerry-core/ecma/base/ecma-globals.h | 17 +++------- jerry-core/include/jerryscript-types.h | 37 +++++++++------------ tests/unit-core/test-api-property.c | 16 ++++++--- 5 files changed, 61 insertions(+), 70 deletions(-) diff --git a/docs/02.API-REFERENCE.md b/docs/02.API-REFERENCE.md index fc9889ee1..b95271885 100644 --- a/docs/02.API-REFERENCE.md +++ b/docs/02.API-REFERENCE.md @@ -559,17 +559,10 @@ the `value` field should contain the value for the property. ```c typedef struct { - /** any combination of jerry_property_descriptor_flags_t bits */ - uint16_t flags; - - /** [[Value]] */ - jerry_value_t value; - - /** [[Get]] */ - jerry_value_t getter; - - /** [[Set]] */ - jerry_value_t setter; + uint16_t flags; /**< any combination of jerry_property_descriptor_flags_t bits */ + jerry_value_t value; /**< [[Value]] */ + jerry_value_t getter; /**< [[Get]] */ + jerry_value_t setter; /**< [[Set]] */ } jerry_property_descriptor_t; ``` diff --git a/jerry-core/api/jerry.c b/jerry-core/api/jerry.c index e70999e18..784b0f5f3 100644 --- a/jerry-core/api/jerry.c +++ b/jerry-core/api/jerry.c @@ -3680,9 +3680,11 @@ jerry_property_descriptor_from_ecma (const ecma_property_descriptor_t *prop_desc /** * Convert a jerry_property_descriptor_t to a ecma_property_descriptor_t * - * if error occurs the property descriptor's value field is filled with ECMA_VALUE_ERROR + * Note: + * if error occurs the property descriptor's value field + * is set to ECMA_VALUE_ERROR, but no error is thrown * - * @return ecma_property_descriptor_t + * @return ecma_property_descriptor_t */ static ecma_property_descriptor_t jerry_property_descriptor_to_ecma (const jerry_property_descriptor_t *prop_desc_p) /**< input property_descriptor */ @@ -3694,9 +3696,10 @@ jerry_property_descriptor_to_ecma (const jerry_property_descriptor_t *prop_desc_ /* Copy data property info. */ if (prop_desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED) { - if (ecma_is_value_error_reference (prop_desc_p->value)) + if (ecma_is_value_error_reference (prop_desc_p->value) + || (prop_desc_p->flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED))) { - prop_desc.value = ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_wrong_args_msg_p)); + prop_desc.value = ECMA_VALUE_ERROR; return prop_desc; } @@ -3710,7 +3713,7 @@ jerry_property_descriptor_to_ecma (const jerry_property_descriptor_t *prop_desc_ if (ecma_is_value_error_reference (getter)) { - prop_desc.value = ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_wrong_args_msg_p)); + prop_desc.value = ECMA_VALUE_ERROR; return prop_desc; } @@ -3720,7 +3723,7 @@ jerry_property_descriptor_to_ecma (const jerry_property_descriptor_t *prop_desc_ } else if (!ecma_is_value_null (getter)) { - prop_desc.value = ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_wrong_args_msg_p)); + prop_desc.value = ECMA_VALUE_ERROR; return prop_desc; } } @@ -3731,7 +3734,7 @@ jerry_property_descriptor_to_ecma (const jerry_property_descriptor_t *prop_desc_ if (ecma_is_value_error_reference (setter)) { - prop_desc.value = ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_wrong_args_msg_p)); + prop_desc.value = ECMA_VALUE_ERROR; return prop_desc; } @@ -3741,7 +3744,7 @@ jerry_property_descriptor_to_ecma (const jerry_property_descriptor_t *prop_desc_ } else if (!ecma_is_value_null (setter)) { - prop_desc.value = ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_wrong_args_msg_p)); + prop_desc.value = ECMA_VALUE_ERROR; return prop_desc; } } @@ -3754,7 +3757,7 @@ jerry_property_descriptor_to_ecma (const jerry_property_descriptor_t *prop_desc_ || (prop_desc_p->flags & enumerable_mask) == JERRY_PROP_IS_ENUMERABLE || (prop_desc_p->flags & writable_mask) == JERRY_PROP_IS_WRITABLE) { - prop_desc.value = ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_wrong_args_msg_p)); + prop_desc.value = ECMA_VALUE_ERROR; return prop_desc; } @@ -3769,11 +3772,16 @@ jerry_property_descriptor_to_ecma (const jerry_property_descriptor_t *prop_desc_ * false value - otherwise */ static jerry_value_t -jerry_error_or_false (const jerry_value_t err_val, /**< error value */ - bool is_throw) /**< throw flag */ +jerry_type_error_or_false (const char *msg_p, /**< message */ + uint16_t flags) /**< property descriptor flags */ { - return is_throw ? jerry_throw (err_val) : jerry_create_boolean (false); -} /* jerry_error_or_false */ + if (!(flags & JERRY_PROP_SHOULD_THROW)) + { + return ECMA_VALUE_FALSE; + } + + return jerry_throw (ecma_raise_type_error (msg_p)); +} /* jerry_type_error_or_false */ /** * Define a property to the specified object with the given name. @@ -3795,24 +3803,22 @@ jerry_define_own_property (const jerry_value_t obj_val, /**< object value */ if (!ecma_is_value_object (obj_val) || !ecma_is_value_prop_name (prop_name_val)) { - return jerry_error_or_false (ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_wrong_args_msg_p)), - prop_desc_p->flags & JERRY_PROP_SHOULD_THROW); + return jerry_type_error_or_false (ECMA_ERR_MSG (ecma_error_wrong_args_msg_p), prop_desc_p->flags); } if (prop_desc_p->flags & (JERRY_PROP_IS_WRITABLE_DEFINED | JERRY_PROP_IS_VALUE_DEFINED) && prop_desc_p->flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED)) { - return jerry_error_or_false (ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_wrong_args_msg_p)), - prop_desc_p->flags & JERRY_PROP_SHOULD_THROW); + return jerry_type_error_or_false (ECMA_ERR_MSG (ecma_error_wrong_args_msg_p), prop_desc_p->flags); } ecma_property_descriptor_t prop_desc = jerry_property_descriptor_to_ecma (prop_desc_p); if (ECMA_IS_VALUE_ERROR (prop_desc.value)) { - return jerry_error_or_false (prop_desc.value, prop_desc_p->flags & JERRY_PROP_SHOULD_THROW); - + return jerry_type_error_or_false (ECMA_ERR_MSG (ecma_error_wrong_args_msg_p), prop_desc_p->flags); } + return jerry_return (ecma_op_object_define_own_property (ecma_get_object_from_value (obj_val), ecma_get_prop_name_from_value (prop_name_val), &prop_desc)); @@ -4688,7 +4694,7 @@ jerry_from_property_descriptor (const jerry_property_descriptor_t *src_prop_desc if (ECMA_IS_VALUE_ERROR (prop_desc.value)) { - return jerry_throw (prop_desc.value); + return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_wrong_args_msg_p))); } ecma_object_t *desc_obj_p = ecma_op_from_property_descriptor (&prop_desc); diff --git a/jerry-core/ecma/base/ecma-globals.h b/jerry-core/ecma/base/ecma-globals.h index d3de6b15b..83a3c7710 100644 --- a/jerry-core/ecma/base/ecma-globals.h +++ b/jerry-core/ecma/base/ecma-globals.h @@ -1310,22 +1310,13 @@ typedef struct * Note: * If a component of descriptor is undefined then corresponding * field should contain it's default value. - * The struct members must be in this order or keep in sync with ecma_property_descriptor_status_flags_t. */ typedef struct { - - /** any combination of ecma_property_descriptor_status_flags_t bits */ - uint16_t flags; - - /** [[Value]] */ - ecma_value_t value; - - /** [[Get]] */ - ecma_object_t *get_p; - - /** [[Set]] */ - ecma_object_t *set_p; + uint16_t flags; /**< any combination of jerry_property_descriptor_flags_t bits */ + ecma_value_t value; /**< [[Value]] */ + ecma_object_t *get_p; /**< [[Get]] */ + ecma_object_t *set_p; /**< [[Set]] */ } ecma_property_descriptor_t; /** diff --git a/jerry-core/include/jerryscript-types.h b/jerry-core/include/jerryscript-types.h index 5b95785c3..834d5a5b1 100644 --- a/jerry-core/include/jerryscript-types.h +++ b/jerry-core/include/jerryscript-types.h @@ -189,20 +189,20 @@ typedef struct */ typedef enum { - JERRY_PROP_NO_OPTS = (0), /** empty property descriptor */ - JERRY_PROP_IS_CONFIGURABLE = (1 << 0), /** [[Configurable]] */ - JERRY_PROP_IS_ENUMERABLE = (1 << 1), /** [[Enumerable]] */ - JERRY_PROP_IS_WRITABLE = (1 << 2), /** [[Writable]] */ + JERRY_PROP_NO_OPTS = (0), /**< empty property descriptor */ + JERRY_PROP_IS_CONFIGURABLE = (1 << 0), /**< [[Configurable]] */ + JERRY_PROP_IS_ENUMERABLE = (1 << 1), /**< [[Enumerable]] */ + JERRY_PROP_IS_WRITABLE = (1 << 2), /**< [[Writable]] */ - JERRY_PROP_IS_CONFIGURABLE_DEFINED = (1 << 3), /** is [[Configurable]] defined? */ - JERRY_PROP_IS_ENUMERABLE_DEFINED = (1 << 4), /** is [[Enumerable]] defined? */ - JERRY_PROP_IS_WRITABLE_DEFINED = (1 << 5), /** is [[Writable]] defined? */ + JERRY_PROP_IS_CONFIGURABLE_DEFINED = (1 << 3), /**< is [[Configurable]] defined? */ + JERRY_PROP_IS_ENUMERABLE_DEFINED = (1 << 4), /**< is [[Enumerable]] defined? */ + JERRY_PROP_IS_WRITABLE_DEFINED = (1 << 5), /**< is [[Writable]] defined? */ - JERRY_PROP_IS_VALUE_DEFINED = (1 << 6), /** is [[Value]] defined? */ - JERRY_PROP_IS_GET_DEFINED = (1 << 7), /** is [[Get]] defined? */ - JERRY_PROP_IS_SET_DEFINED = (1 << 8), /** is [[Set]] defined? */ + JERRY_PROP_IS_VALUE_DEFINED = (1 << 6), /**< is [[Value]] defined? */ + JERRY_PROP_IS_GET_DEFINED = (1 << 7), /**< is [[Get]] defined? */ + JERRY_PROP_IS_SET_DEFINED = (1 << 8), /**< is [[Set]] defined? */ - JERRY_PROP_SHOULD_THROW = (1 << 9), /** should throw on error, instead of returning with false */ + JERRY_PROP_SHOULD_THROW = (1 << 9), /**< should throw on error, instead of returning with false */ } jerry_property_descriptor_flags_t; /** @@ -210,17 +210,10 @@ typedef enum */ typedef struct { - /** any combination of jerry_property_descriptor_flags_t bits */ - uint16_t flags; - - /** [[Value]] */ - jerry_value_t value; - - /** [[Get]] */ - jerry_value_t getter; - - /** [[Set]] */ - jerry_value_t setter; + uint16_t flags; /**< any combination of jerry_property_descriptor_flags_t bits */ + jerry_value_t value; /**< [[Value]] */ + jerry_value_t getter; /**< [[Get]] */ + jerry_value_t setter; /**< [[Set]] */ } jerry_property_descriptor_t; /** diff --git a/tests/unit-core/test-api-property.c b/tests/unit-core/test-api-property.c index 9ae8077fc..a7422237b 100644 --- a/tests/unit-core/test-api-property.c +++ b/tests/unit-core/test-api-property.c @@ -37,9 +37,7 @@ main (void) prop_desc.flags |= JERRY_PROP_IS_VALUE_DEFINED; prop_desc.value = jerry_acquire_value (prop_name); jerry_value_t res = jerry_define_own_property (global_obj_val, prop_name, &prop_desc); - TEST_ASSERT (!jerry_value_is_error (res)); - TEST_ASSERT (jerry_value_is_boolean (res)); - TEST_ASSERT (jerry_get_boolean_value (res)); + TEST_ASSERT (jerry_value_is_boolean (res) && jerry_get_boolean_value (res)); jerry_release_value (res); jerry_property_descriptor_free (&prop_desc); @@ -49,7 +47,17 @@ main (void) prop_desc.value = jerry_create_number (3.14); res = jerry_define_own_property (global_obj_val, prop_name, &prop_desc); TEST_ASSERT (jerry_value_is_error (res)); - TEST_ASSERT (!jerry_value_is_boolean (res)); + jerry_release_value (res); + jerry_property_descriptor_free (&prop_desc); + + /* Test: test define own property failure without throw twice */ + prop_desc = jerry_property_descriptor_create (); + prop_desc.flags |= JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_GET_DEFINED; + res = jerry_define_own_property (prop_name, prop_name, &prop_desc); + TEST_ASSERT (jerry_value_is_boolean (res) && !jerry_get_boolean_value (res)); + jerry_release_value (res); + res = jerry_define_own_property (global_obj_val, prop_name, &prop_desc); + TEST_ASSERT (jerry_value_is_boolean (res) && !jerry_get_boolean_value (res)); jerry_release_value (res); jerry_property_descriptor_free (&prop_desc);