Improve ecma_reject to give more detailed error messages (#4565)

Note: TypedArray.[[DefineOwnProperty]] has been slightly reworked (without semantical changes) for better error messages.

JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu
This commit is contained in:
Robert Fancsik
2021-02-24 09:36:55 +01:00
committed by GitHub
parent 1623c8db1e
commit f0f2a28109
8 changed files with 174 additions and 167 deletions
@@ -970,9 +970,8 @@ ecma_delete_array_properties (ecma_object_t *object_p, /**< object */
ecma_value_t ecma_value_t
ecma_op_array_object_set_length (ecma_object_t *object_p, /**< the array object */ ecma_op_array_object_set_length (ecma_object_t *object_p, /**< the array object */
ecma_value_t new_value, /**< new length value */ ecma_value_t new_value, /**< new length value */
uint32_t flags) /**< configuration options */ uint16_t flags) /**< property descriptor flags */
{ {
bool is_throw = (flags & ECMA_PROP_IS_THROW) != 0;
ecma_number_t new_len_num; ecma_number_t new_len_num;
ecma_value_t completion = ecma_op_to_number (new_value, &new_len_num); ecma_value_t completion = ecma_op_to_number (new_value, &new_len_num);
@@ -1006,7 +1005,7 @@ ecma_op_array_object_set_length (ecma_object_t *object_p, /**< the array object
| ECMA_PROP_IS_GET_DEFINED | ECMA_PROP_IS_GET_DEFINED
| ECMA_PROP_IS_SET_DEFINED)) | ECMA_PROP_IS_SET_DEFINED))
{ {
return ecma_reject (is_throw); return ecma_raise_property_redefinition (ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH), flags);
} }
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
@@ -1029,14 +1028,14 @@ ecma_op_array_object_set_length (ecma_object_t *object_p, /**< the array object
} }
else if (!ecma_is_property_writable ((ecma_property_t) ext_object_p->u.array.length_prop_and_hole_count)) else if (!ecma_is_property_writable ((ecma_property_t) ext_object_p->u.array.length_prop_and_hole_count))
{ {
return ecma_reject (is_throw); return ecma_raise_property_redefinition (ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH), flags);
} }
} }
return ECMA_VALUE_TRUE; return ECMA_VALUE_TRUE;
} }
else if (!ecma_is_property_writable ((ecma_property_t) ext_object_p->u.array.length_prop_and_hole_count)) else if (!ecma_is_property_writable ((ecma_property_t) ext_object_p->u.array.length_prop_and_hole_count))
{ {
return ecma_reject (is_throw); return ecma_raise_property_redefinition (ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH), flags);
} }
uint32_t current_len_uint32 = new_len_uint32; uint32_t current_len_uint32 = new_len_uint32;
@@ -1067,7 +1066,8 @@ ecma_op_array_object_set_length (ecma_object_t *object_p, /**< the array object
{ {
return ECMA_VALUE_TRUE; return ECMA_VALUE_TRUE;
} }
return ecma_reject (is_throw);
return ecma_raise_property_redefinition (ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH), flags);
} /* ecma_op_array_object_set_length */ } /* ecma_op_array_object_set_length */
/** /**
@@ -1159,7 +1159,7 @@ ecma_op_array_object_define_own_property (ecma_object_t *object_p, /**< the arra
if (update_length if (update_length
&& !ecma_is_property_writable ((ecma_property_t) ext_object_p->u.array.length_prop_and_hole_count)) && !ecma_is_property_writable ((ecma_property_t) ext_object_p->u.array.length_prop_and_hole_count))
{ {
return ecma_reject (property_desc_p->flags & ECMA_PROP_IS_THROW); return ecma_raise_property_redefinition (property_name_p, property_desc_p->flags);
} }
ecma_property_descriptor_t prop_desc; ecma_property_descriptor_t prop_desc;
@@ -1174,7 +1174,7 @@ ecma_op_array_object_define_own_property (ecma_object_t *object_p, /**< the arra
if (ecma_is_value_false (completition)) if (ecma_is_value_false (completition))
{ {
return ecma_reject (property_desc_p->flags & ECMA_PROP_IS_THROW); return ecma_raise_property_redefinition (property_name_p, property_desc_p->flags);
} }
if (update_length) if (update_length)
@@ -113,7 +113,7 @@ ecma_op_create_array_iterator (ecma_object_t *obj_p,
#endif /* JERRY_ESNEXT */ #endif /* JERRY_ESNEXT */
ecma_value_t ecma_value_t
ecma_op_array_object_set_length (ecma_object_t *object_p, ecma_value_t new_value, uint32_t flags); ecma_op_array_object_set_length (ecma_object_t *object_p, ecma_value_t new_value, uint16_t flags);
ecma_value_t ecma_value_t
ecma_op_array_object_define_own_property (ecma_object_t *object_p, ecma_string_t *property_name_p, ecma_op_array_object_define_own_property (ecma_object_t *object_p, ecma_string_t *property_name_p,
@@ -31,25 +31,6 @@
* @{ * @{
*/ */
/**
* Reject sequence
*
* @return ecma value
* Returned value must be freed with ecma_free_value
*/
ecma_value_t
ecma_reject (bool is_throw) /**< Throw flag */
{
if (is_throw)
{
return ecma_raise_type_error (ECMA_ERR_MSG ("Invalid argument type"));
}
else
{
return ECMA_VALUE_FALSE;
}
} /* ecma_reject */
/** /**
* 'Object' object creation operation with no arguments. * 'Object' object creation operation with no arguments.
* *
@@ -386,7 +367,9 @@ ecma_op_general_object_define_own_property (ecma_object_t *object_p, /**< the ob
if (!ecma_op_ordinary_object_is_extensible (object_p)) if (!ecma_op_ordinary_object_is_extensible (object_p))
{ {
/* 2. */ /* 2. */
return ecma_reject (property_desc_p->flags & ECMA_PROP_IS_THROW); return ECMA_REJECT_WITH_FORMAT (property_desc_p->flags & ECMA_PROP_IS_THROW,
"Cannot define property '%', object is not extensible",
ecma_make_prop_name_value (property_name_p));
} }
/* 4. */ /* 4. */
@@ -436,7 +419,8 @@ ecma_op_general_object_define_own_property (ecma_object_t *object_p, /**< the ob
{ {
ecma_free_value (ext_property_ref.property_ref.virtual_value); ecma_free_value (ext_property_ref.property_ref.virtual_value);
} }
return ecma_reject (property_desc_p->flags & ECMA_PROP_IS_THROW);
return ecma_raise_property_redefinition (property_name_p, property_desc_p->flags);
} }
if (ECMA_PROPERTY_IS_VIRTUAL (current_prop)) if (ECMA_PROPERTY_IS_VIRTUAL (current_prop))
@@ -451,7 +435,7 @@ ecma_op_general_object_define_own_property (ecma_object_t *object_p, /**< the ob
&& !ecma_op_same_value (property_desc_p->value, && !ecma_op_same_value (property_desc_p->value,
ext_property_ref.property_ref.virtual_value))) ext_property_ref.property_ref.virtual_value)))
{ {
result = ecma_reject (property_desc_p->flags & ECMA_PROP_IS_THROW); result = ecma_raise_property_redefinition (property_name_p, property_desc_p->flags);
} }
ecma_free_value (ext_property_ref.property_ref.virtual_value); ecma_free_value (ext_property_ref.property_ref.virtual_value);
@@ -477,7 +461,7 @@ ecma_op_general_object_define_own_property (ecma_object_t *object_p, /**< the ob
&& !ecma_op_same_value (property_desc_p->value, && !ecma_op_same_value (property_desc_p->value,
ext_property_ref.property_ref.value_p->value)))) ext_property_ref.property_ref.value_p->value))))
{ {
return ecma_reject (property_desc_p->flags & ECMA_PROP_IS_THROW); return ecma_raise_property_redefinition (property_name_p, property_desc_p->flags);
} }
} }
else else
@@ -498,7 +482,7 @@ ecma_op_general_object_define_own_property (ecma_object_t *object_p, /**< the ob
&& prop_desc_setter_cp != get_set_pair_p->setter_cp)) && prop_desc_setter_cp != get_set_pair_p->setter_cp))
{ {
/* i., ii. */ /* i., ii. */
return ecma_reject (property_desc_p->flags & ECMA_PROP_IS_THROW); return ecma_raise_property_redefinition (property_name_p, property_desc_p->flags);
} }
} }
} }
@@ -509,7 +493,7 @@ ecma_op_general_object_define_own_property (ecma_object_t *object_p, /**< the ob
if (!is_current_configurable) if (!is_current_configurable)
{ {
/* a. */ /* a. */
return ecma_reject (property_desc_p->flags & ECMA_PROP_IS_THROW); return ecma_raise_property_redefinition (property_name_p, property_desc_p->flags);
} }
ecma_property_value_t *value_p = ext_property_ref.property_ref.value_p; ecma_property_value_t *value_p = ext_property_ref.property_ref.value_p;
@@ -26,7 +26,6 @@
* @{ * @{
*/ */
ecma_value_t ecma_reject (bool is_throw);
ecma_object_t *ecma_op_create_object_object_noarg (void); ecma_object_t *ecma_op_create_object_object_noarg (void);
ecma_object_t *ecma_op_create_object_object_noarg_and_set_prototype (ecma_object_t *object_prototype_p); ecma_object_t *ecma_op_create_object_object_noarg_and_set_prototype (ecma_object_t *object_prototype_p);
+74 -98
View File
@@ -1126,7 +1126,7 @@ ecma_op_object_put_apply_receiver (ecma_value_t receiver, /**< receiver */
/* 5.b */ /* 5.b */
if (!ecma_is_value_object (receiver)) if (!ecma_is_value_object (receiver))
{ {
return ecma_reject (is_throw); return ECMA_REJECT (is_throw, "Receiver must be an object");
} }
ecma_object_t *receiver_obj_p = ecma_get_object_from_value (receiver); ecma_object_t *receiver_obj_p = ecma_get_object_from_value (receiver);
@@ -1152,7 +1152,7 @@ ecma_op_object_put_apply_receiver (ecma_value_t receiver, /**< receiver */
if (prop_desc.flags & (ECMA_PROP_IS_GET_DEFINED | ECMA_PROP_IS_SET_DEFINED) if (prop_desc.flags & (ECMA_PROP_IS_GET_DEFINED | ECMA_PROP_IS_SET_DEFINED)
|| !(prop_desc.flags & ECMA_PROP_IS_WRITABLE)) || !(prop_desc.flags & ECMA_PROP_IS_WRITABLE))
{ {
result = ecma_reject (is_throw); result = ecma_raise_property_redefinition (property_name_p, prop_desc.flags);
} }
else else
{ {
@@ -1164,9 +1164,9 @@ ecma_op_object_put_apply_receiver (ecma_value_t receiver, /**< receiver */
/* 5.e.iv */ /* 5.e.iv */
result = ecma_op_object_define_own_property (receiver_obj_p, property_name_p, &prop_desc); result = ecma_op_object_define_own_property (receiver_obj_p, property_name_p, &prop_desc);
if (JERRY_UNLIKELY (ecma_is_value_false (result)) && is_throw) if (JERRY_UNLIKELY (ecma_is_value_false (result)))
{ {
result = ecma_raise_type_error (ECMA_ERR_MSG ("Proxy trap returned falsish")); result = ECMA_REJECT (is_throw, "Proxy trap returned falsish");
} }
} }
@@ -1190,9 +1190,9 @@ ecma_op_object_put_apply_receiver (ecma_value_t receiver, /**< receiver */
desc.value = value; desc.value = value;
ecma_value_t ret_value = ecma_proxy_object_define_own_property (receiver_obj_p, property_name_p, &desc); ecma_value_t ret_value = ecma_proxy_object_define_own_property (receiver_obj_p, property_name_p, &desc);
if (JERRY_UNLIKELY (ecma_is_value_false (ret_value)) && is_throw) if (JERRY_UNLIKELY (ecma_is_value_false (ret_value)))
{ {
ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Proxy trap returned falsish")); ret_value = ECMA_REJECT (is_throw, "Proxy trap returned falsish");
} }
return ret_value; return ret_value;
@@ -1269,7 +1269,7 @@ ecma_op_object_put_with_receiver (ecma_object_t *object_p, /**< the object */
return ecma_op_array_object_set_length (object_p, value, 0); return ecma_op_array_object_set_length (object_p, value, 0);
} }
return ecma_reject (is_throw); return ecma_raise_readonly_assignment (property_name_p, is_throw);
} }
if (JERRY_LIKELY (ecma_op_array_is_fast_array (ext_object_p))) if (JERRY_LIKELY (ecma_op_array_is_fast_array (ext_object_p)))
@@ -1391,7 +1391,7 @@ ecma_op_object_put_with_receiver (ecma_object_t *object_p, /**< the object */
if (index < ecma_string_get_length (prim_value_str_p)) if (index < ecma_string_get_length (prim_value_str_p))
{ {
return ecma_reject (is_throw); return ecma_raise_readonly_assignment (property_name_p, is_throw);
} }
} }
} }
@@ -1399,19 +1399,16 @@ ecma_op_object_put_with_receiver (ecma_object_t *object_p, /**< the object */
} }
case ECMA_OBJECT_TYPE_FUNCTION: case ECMA_OBJECT_TYPE_FUNCTION:
{ {
#if JERRY_ESNEXT
/* Uninitialized 'length' property is non-writable (ECMA-262 v6, 19.2.4.1) */
if ((ecma_string_is_length (property_name_p))
&& (!ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (((ecma_extended_object_t *) object_p)->u.function.scope_cp)))
{
return ecma_reject (is_throw);
}
#else /* !JERRY_ESNEXT */
if (ecma_string_is_length (property_name_p)) if (ecma_string_is_length (property_name_p))
{ {
return ecma_reject (is_throw); /* Uninitialized 'length' property is non-writable (ECMA-262 v6, 19.2.4.1) */
} #if JERRY_ESNEXT
if (!ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (((ecma_extended_object_t *) object_p)->u.function.scope_cp))
#endif /* JERRY_ESNEXT */ #endif /* JERRY_ESNEXT */
{
return ecma_raise_readonly_assignment (property_name_p, is_throw);
}
}
/* Get prototype physical property. */ /* Get prototype physical property. */
property_p = ecma_op_function_try_to_lazy_instantiate_property (object_p, property_name_p); property_p = ecma_op_function_try_to_lazy_instantiate_property (object_p, property_name_p);
@@ -1568,7 +1565,7 @@ ecma_op_object_put_with_receiver (ecma_object_t *object_p, /**< the object */
{ {
if (!ecma_is_property_writable ((ecma_property_t) ext_object_p->u.array.length_prop_and_hole_count)) if (!ecma_is_property_writable ((ecma_property_t) ext_object_p->u.array.length_prop_and_hole_count))
{ {
return ecma_reject (is_throw); return ecma_raise_readonly_assignment (property_name_p, is_throw);
} }
ext_object_p->u.array.length = index + 1; ext_object_p->u.array.length = index + 1;
@@ -1593,7 +1590,7 @@ ecma_op_object_put_with_receiver (ecma_object_t *object_p, /**< the object */
if (setter_cp == JMEM_CP_NULL) if (setter_cp == JMEM_CP_NULL)
{ {
return ecma_reject (is_throw); return ecma_raise_readonly_assignment (property_name_p, is_throw);
} }
ecma_value_t ret_value = ecma_op_function_call (ECMA_GET_NON_NULL_POINTER (ecma_object_t, setter_cp), ecma_value_t ret_value = ecma_op_function_call (ECMA_GET_NON_NULL_POINTER (ecma_object_t, setter_cp),
@@ -1741,99 +1738,44 @@ ecma_op_object_define_own_property (ecma_object_t *obj_p, /**< the object */
const ecma_object_type_t type = ecma_get_object_type (obj_p); const ecma_object_type_t type = ecma_get_object_type (obj_p);
#if JERRY_BUILTIN_PROXY
if (ECMA_OBJECT_IS_PROXY (obj_p))
{
return ecma_proxy_object_define_own_property (obj_p, property_name_p, property_desc_p);
}
#endif /* JERRY_BUILTIN_PROXY */
switch (type) switch (type)
{ {
case ECMA_OBJECT_TYPE_GENERAL: #if JERRY_BUILTIN_PROXY
case ECMA_OBJECT_TYPE_CLASS: case ECMA_OBJECT_TYPE_PROXY:
case ECMA_OBJECT_TYPE_FUNCTION:
case ECMA_OBJECT_TYPE_NATIVE_FUNCTION:
case ECMA_OBJECT_TYPE_BOUND_FUNCTION:
{ {
return ecma_op_general_object_define_own_property (obj_p, return ecma_proxy_object_define_own_property (obj_p, property_name_p, property_desc_p);
property_name_p,
property_desc_p);
} }
#endif /* JERRY_BUILTIN_PROXY */
case ECMA_OBJECT_TYPE_ARRAY: case ECMA_OBJECT_TYPE_ARRAY:
{ {
return ecma_op_array_object_define_own_property (obj_p, return ecma_op_array_object_define_own_property (obj_p, property_name_p, property_desc_p);
property_name_p,
property_desc_p);
} }
case ECMA_OBJECT_TYPE_PSEUDO_ARRAY:
default:
{ {
JERRY_ASSERT (type == ECMA_OBJECT_TYPE_PSEUDO_ARRAY);
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p;
#if JERRY_BUILTIN_TYPEDARRAY #if JERRY_BUILTIN_TYPEDARRAY
if (ext_object_p->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS)
{
#else /* !JERRY_BUILTIN_TYPEDARRAY */
JERRY_ASSERT (ext_object_p->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS);
#endif /* JERRY_BUILTIN_TYPEDARRAY */
return ecma_op_arguments_object_define_own_property (obj_p,
property_name_p,
property_desc_p);
#if JERRY_BUILTIN_TYPEDARRAY
}
/* ES2015 9.4.5.3 */
if (ecma_object_is_typedarray (obj_p)) if (ecma_object_is_typedarray (obj_p))
{ {
if (ecma_prop_name_is_symbol (property_name_p)) return ecma_op_typedarray_define_own_property (obj_p, property_name_p, property_desc_p);
{
return ecma_op_general_object_define_own_property (obj_p,
property_name_p,
property_desc_p);
}
uint32_t array_index = ecma_string_get_array_index (property_name_p);
if (array_index != ECMA_STRING_NOT_ARRAY_INDEX)
{
ecma_value_t define_status = ecma_op_typedarray_define_index_prop (obj_p,
array_index,
property_desc_p);
if (ECMA_IS_VALUE_ERROR (define_status))
{
return define_status;
}
if (ecma_is_value_true (define_status))
{
return ECMA_VALUE_TRUE;
}
return ecma_reject (property_desc_p->flags & ECMA_PROP_IS_THROW);
}
ecma_number_t num = ecma_string_to_number (property_name_p);
ecma_string_t *num_to_str = ecma_new_ecma_string_from_number (num);
bool is_same = ecma_compare_ecma_strings (property_name_p, num_to_str);
ecma_deref_ecma_string (num_to_str);
if (is_same)
{
return ecma_reject (property_desc_p->flags & ECMA_PROP_IS_THROW);
}
} }
return ecma_op_general_object_define_own_property (obj_p,
property_name_p,
property_desc_p);
#else /* !JERRY_BUILTIN_TYPEDARRAY */
break;
#endif /* JERRY_BUILTIN_TYPEDARRAY */ #endif /* JERRY_BUILTIN_TYPEDARRAY */
#if JERRY_ESNEXT
/* All iterators are pseudo arrays */
if (((ecma_extended_object_t *) obj_p)->u.pseudo_array.type != ECMA_PSEUDO_ARRAY_ARGUMENTS)
{
break;
}
#endif /* JERRY_ESNEXT */
return ecma_op_arguments_object_define_own_property (obj_p, property_name_p, property_desc_p);
}
default:
{
break;
} }
} }
return ecma_op_general_object_define_own_property (obj_p, property_name_p, property_desc_p);
} /* ecma_op_object_define_own_property */ } /* ecma_op_object_define_own_property */
/** /**
@@ -3297,6 +3239,40 @@ ecma_op_ordinary_object_has_own_property (ecma_object_t *object_p, /**< the obje
return property != ECMA_PROPERTY_TYPE_NOT_FOUND && property != ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP; return property != ECMA_PROPERTY_TYPE_NOT_FOUND && property != ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP;
} /* ecma_op_ordinary_object_has_own_property */ } /* ecma_op_ordinary_object_has_own_property */
/**
* Raise property redefinition error
*
* @return ECMA_VALUE_FALSE - if ECMA_IS_THROW is not set
* raised TypeError - otherwise
*/
ecma_value_t
ecma_raise_property_redefinition (ecma_string_t *property_name_p, /**< property name */
uint16_t flags) /**< property descriptor flags */
{
JERRY_UNUSED (property_name_p);
return ECMA_REJECT_WITH_FORMAT (flags & ECMA_PROP_IS_THROW,
"Cannot redefine property '%'",
ecma_make_prop_name_value (property_name_p));
} /* ecma_raise_property_redefinition */
/**
* Raise readonly assignment error
*
* @return ECMA_VALUE_FALSE - if is_throw is true
* raised TypeError - otherwise
*/
ecma_value_t
ecma_raise_readonly_assignment (ecma_string_t *property_name_p, /**< property name */
bool is_throw) /**< is throw flag */
{
JERRY_UNUSED (property_name_p);
return ECMA_REJECT_WITH_FORMAT (is_throw,
"Cannot assign to read only property '%'",
ecma_make_prop_name_value (property_name_p));
} /* ecma_raise_readonly_assignment */
/** /**
* @} * @}
* @} * @}
+29
View File
@@ -27,6 +27,35 @@
* @{ * @{
*/ */
#if JERRY_ERROR_MESSAGES
/**
* Reject with TypeError depending on 'is_throw' with the given format
*/
#define ECMA_REJECT_WITH_FORMAT(is_throw, msg, ...) \
((is_throw) ? ecma_raise_standard_error_with_format (ECMA_ERROR_TYPE, (msg), __VA_ARGS__) : ECMA_VALUE_FALSE)
/**
* Reject with TypeError depending on 'is_throw' with the given message
*/
#define ECMA_REJECT(is_throw, msg) \
((is_throw) ? ecma_raise_type_error (msg) : ECMA_VALUE_FALSE)
#else /* !JERRY_ERROR_MESSAGES */
/**
* Reject with TypeError depending on is_throw flags wit the given format
*/
#define ECMA_REJECT_WITH_FORMAT(is_throw, msg, ...) \
ECMA_REJECT((is_throw), (msg))
/**
* Reject with TypeError depending on is_throw flags wit the given message
*/
#define ECMA_REJECT(is_throw, msg) \
((is_throw) ? ecma_raise_type_error (NULL) : ECMA_VALUE_FALSE)
#endif /* JERRY_ERROR_MESSAGES */
ecma_value_t ecma_raise_property_redefinition (ecma_string_t *property_name_p, uint16_t flags);
ecma_value_t ecma_raise_readonly_assignment (ecma_string_t *property_name_p, bool is_throw);
ecma_property_t ecma_op_object_get_own_property (ecma_object_t *object_p, ecma_string_t *property_name_p, ecma_property_t ecma_op_object_get_own_property (ecma_object_t *object_p, ecma_string_t *property_name_p,
ecma_property_ref_t *property_ref_p, uint32_t options); ecma_property_ref_t *property_ref_p, uint32_t options);
bool ecma_op_ordinary_object_has_own_property (ecma_object_t *object_p, ecma_string_t *property_name_p); bool ecma_op_ordinary_object_has_own_property (ecma_object_t *object_p, ecma_string_t *property_name_p);
@@ -23,6 +23,7 @@
#include "ecma-big-uint.h" #include "ecma-big-uint.h"
#include "ecma-builtin-helpers.h" #include "ecma-builtin-helpers.h"
#include "ecma-objects.h" #include "ecma-objects.h"
#include "ecma-objects-general.h"
#include "ecma-builtins.h" #include "ecma-builtins.h"
#include "ecma-exceptions.h" #include "ecma-exceptions.h"
#include "ecma-gc.h" #include "ecma-gc.h"
@@ -1564,54 +1565,72 @@ ecma_op_typedarray_list_lazy_property_names (ecma_object_t *obj_p, /**< a TypedA
} /* ecma_op_typedarray_list_lazy_property_names */ } /* ecma_op_typedarray_list_lazy_property_names */
/** /**
* Define the integer number property value of the typedarray * [[DefineOwnProperty]] operation for TypedArray objects
* *
* See also: ES2015 9.4.5.3: 3.c * See also: ES2015 9.4.5.3
* *
* @return ecma value, * @return ECMA_VALUE_TRUE - if the property is successfully defined
* ECMA_VALUE_FALSE - if is ECMA_IS_THROW is not set
* raised TypeError - otherwise
*/ */
ecma_value_t ecma_value_t
ecma_op_typedarray_define_index_prop (ecma_object_t *obj_p, /**< a TypedArray object */ ecma_op_typedarray_define_own_property (ecma_object_t *obj_p, /**< TypedArray object */
uint32_t index, /**< the index number */ ecma_string_t *prop_name_p, /**< property name */
const ecma_property_descriptor_t *property_desc_p) /**< the description of const ecma_property_descriptor_t *property_desc_p) /**< property descriptor */
the prop */
{ {
JERRY_ASSERT (ecma_object_is_typedarray (obj_p)); JERRY_ASSERT (ecma_object_is_typedarray (obj_p));
uint32_t array_length = ecma_typedarray_get_length (obj_p); if (!ecma_prop_name_is_symbol (prop_name_p))
if ((index >= array_length)
|| (property_desc_p->flags & (ECMA_PROP_IS_GET_DEFINED | ECMA_PROP_IS_SET_DEFINED))
|| ((property_desc_p->flags & (ECMA_PROP_IS_CONFIGURABLE_DEFINED | ECMA_PROP_IS_CONFIGURABLE))
== (ECMA_PROP_IS_CONFIGURABLE_DEFINED | ECMA_PROP_IS_CONFIGURABLE))
|| ((property_desc_p->flags & ECMA_PROP_IS_ENUMERABLE_DEFINED)
&& !(property_desc_p->flags & ECMA_PROP_IS_ENUMERABLE))
|| ((property_desc_p->flags & ECMA_PROP_IS_WRITABLE_DEFINED)
&& !(property_desc_p->flags & ECMA_PROP_IS_WRITABLE)))
{ {
return ECMA_VALUE_FALSE; uint32_t array_index = ecma_string_get_array_index (prop_name_p);
}
if (property_desc_p->flags & ECMA_PROP_IS_VALUE_DEFINED) if (array_index != ECMA_STRING_NOT_ARRAY_INDEX)
{
ecma_typedarray_info_t info = ecma_typedarray_get_info (obj_p);
if (index >= info.length)
{ {
return ECMA_VALUE_FALSE; if ((property_desc_p->flags & (ECMA_PROP_IS_GET_DEFINED | ECMA_PROP_IS_SET_DEFINED))
|| ((property_desc_p->flags & (ECMA_PROP_IS_CONFIGURABLE_DEFINED | ECMA_PROP_IS_CONFIGURABLE))
== (ECMA_PROP_IS_CONFIGURABLE_DEFINED | ECMA_PROP_IS_CONFIGURABLE))
|| ((property_desc_p->flags & ECMA_PROP_IS_ENUMERABLE_DEFINED)
&& !(property_desc_p->flags & ECMA_PROP_IS_ENUMERABLE))
|| ((property_desc_p->flags & ECMA_PROP_IS_WRITABLE_DEFINED)
&& !(property_desc_p->flags & ECMA_PROP_IS_WRITABLE)))
{
return ecma_raise_property_redefinition (prop_name_p, property_desc_p->flags);
}
ecma_typedarray_info_t info = ecma_typedarray_get_info (obj_p);
if (array_index >= info.length)
{
return ECMA_REJECT ((property_desc_p->flags & ECMA_PROP_IS_THROW), "Invalid typed array index");
}
if (property_desc_p->flags & ECMA_PROP_IS_VALUE_DEFINED)
{
lit_utf8_byte_t *src_buffer = info.buffer_p + (array_index << info.shift);
ecma_value_t set_element = ecma_set_typedarray_element (src_buffer, property_desc_p->value, info.id);
if (ECMA_IS_VALUE_ERROR (set_element))
{
return set_element;
}
}
return ECMA_VALUE_TRUE;
} }
lit_utf8_byte_t *src_buffer = info.buffer_p + (index << info.shift); ecma_number_t num = ecma_string_to_number (prop_name_p);
ecma_value_t set_element = ecma_set_typedarray_element (src_buffer, property_desc_p->value, info.id); ecma_string_t *num_to_str = ecma_new_ecma_string_from_number (num);
bool is_same = ecma_compare_ecma_strings (prop_name_p, num_to_str);
ecma_deref_ecma_string (num_to_str);
if (ECMA_IS_VALUE_ERROR (set_element)) if (is_same)
{ {
return set_element; return ECMA_REJECT ((property_desc_p->flags & ECMA_PROP_IS_THROW), "Invalid typed array index");
} }
} }
return ECMA_VALUE_TRUE; return ecma_op_general_object_define_own_property (obj_p, prop_name_p, property_desc_p);
} /* ecma_op_typedarray_define_index_prop */ } /* ecma_op_typedarray_define_own_property */
/** /**
* Specify the creation of a new TypedArray * Specify the creation of a new TypedArray
@@ -66,9 +66,9 @@ bool ecma_is_typedarray (ecma_value_t target);
void ecma_op_typedarray_list_lazy_property_names (ecma_object_t *obj_p, void ecma_op_typedarray_list_lazy_property_names (ecma_object_t *obj_p,
ecma_collection_t *prop_names_p, ecma_collection_t *prop_names_p,
ecma_property_counter_t *prop_counter_p); ecma_property_counter_t *prop_counter_p);
ecma_value_t ecma_op_typedarray_define_index_prop (ecma_object_t *obj_p, ecma_value_t ecma_op_typedarray_define_own_property (ecma_object_t *obj_p,
uint32_t index, ecma_string_t *prop_name_p,
const ecma_property_descriptor_t *property_desc_p); const ecma_property_descriptor_t *property_desc_p);
ecma_value_t ecma_op_create_typedarray_with_type_and_length (ecma_typedarray_type_t typedarray_id, ecma_value_t ecma_op_create_typedarray_with_type_and_length (ecma_typedarray_type_t typedarray_id,
uint32_t array_length); uint32_t array_length);
ecma_typedarray_info_t ecma_typedarray_get_info (ecma_object_t *typedarray_p); ecma_typedarray_info_t ecma_typedarray_get_info (ecma_object_t *typedarray_p);