mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Use ecma_op_object_get_property_names for property enumeration in built-ins implementation.
JerryScript-DCO-1.0-Signed-off-by: Ruben Ayrapetyan r.ayrapetyan@samsung.com
This commit is contained in:
parent
72208a61ee
commit
09b4d20718
@ -1222,73 +1222,58 @@ ecma_builtin_array_prototype_object_sort (ecma_value_t this_arg, /**< this argum
|
||||
|
||||
uint32_t len = ecma_number_to_uint32 (len_number);
|
||||
|
||||
uint32_t defined_prop_count = 0;
|
||||
/* Count number of array index properties. */
|
||||
for (ecma_property_t *property_p = ecma_get_property_list (obj_p);
|
||||
property_p != NULL;
|
||||
property_p = ECMA_GET_POINTER (ecma_property_t, property_p->next_property_p))
|
||||
{
|
||||
ecma_string_t *property_name_p;
|
||||
ecma_collection_header_t *array_index_props_p = ecma_op_object_get_property_names (obj_p, true, false, false);
|
||||
|
||||
if (property_p->type == ECMA_PROPERTY_NAMEDDATA)
|
||||
{
|
||||
property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
property_p->u.named_data_property.name_p);
|
||||
}
|
||||
else if (property_p->type == ECMA_PROPERTY_NAMEDACCESSOR)
|
||||
{
|
||||
property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
property_p->u.named_accessor_property.name_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
uint32_t defined_prop_count = 0;
|
||||
uint32_t copied_num = 0;
|
||||
|
||||
ecma_collection_iterator_t iter;
|
||||
ecma_collection_iterator_init (&iter, array_index_props_p);
|
||||
|
||||
/* Count properties with name that is array index less than len */
|
||||
while (ecma_collection_iterator_next (&iter)
|
||||
&& ecma_is_completion_value_empty (ret_value))
|
||||
{
|
||||
ecma_string_t *property_name_p = ecma_get_string_from_value (*iter.current_value_p);
|
||||
|
||||
uint32_t index;
|
||||
if (ecma_string_get_array_index (property_name_p, &index) && index < len)
|
||||
bool is_index = ecma_string_get_array_index (property_name_p, &index);
|
||||
JERRY_ASSERT (is_index);
|
||||
|
||||
if (index < len)
|
||||
{
|
||||
defined_prop_count++;
|
||||
}
|
||||
}
|
||||
|
||||
MEM_DEFINE_LOCAL_ARRAY (values_buffer, defined_prop_count, ecma_value_t);
|
||||
uint32_t copied_num = 0;
|
||||
|
||||
ecma_collection_iterator_init (&iter, array_index_props_p);
|
||||
|
||||
/* Copy unsorted array into a native c array. */
|
||||
for (ecma_property_t *property_p = ecma_get_property_list (obj_p);
|
||||
property_p != NULL && ecma_is_completion_value_empty (ret_value);
|
||||
property_p = ECMA_GET_POINTER (ecma_property_t, property_p->next_property_p))
|
||||
while (ecma_collection_iterator_next (&iter)
|
||||
&& ecma_is_completion_value_empty (ret_value))
|
||||
{
|
||||
ecma_string_t *property_name_p;
|
||||
|
||||
if (property_p->type == ECMA_PROPERTY_NAMEDDATA)
|
||||
{
|
||||
property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
property_p->u.named_data_property.name_p);
|
||||
}
|
||||
else if (property_p->type == ECMA_PROPERTY_NAMEDACCESSOR)
|
||||
{
|
||||
property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
property_p->u.named_accessor_property.name_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
ecma_string_t *property_name_p = ecma_get_string_from_value (*iter.current_value_p);
|
||||
|
||||
uint32_t index;
|
||||
if (ecma_string_get_array_index (property_name_p, &index) && index < len)
|
||||
bool is_index = ecma_string_get_array_index (property_name_p, &index);
|
||||
JERRY_ASSERT (is_index);
|
||||
|
||||
if (index >= len)
|
||||
{
|
||||
ECMA_TRY_CATCH (index_value, ecma_op_object_get (obj_p, property_name_p), ret_value);
|
||||
|
||||
values_buffer[copied_num++] = ecma_copy_value (index_value, true);
|
||||
|
||||
ECMA_FINALIZE (index_value);
|
||||
break;
|
||||
}
|
||||
|
||||
ECMA_TRY_CATCH (index_value, ecma_op_object_get (obj_p, property_name_p), ret_value);
|
||||
|
||||
values_buffer[copied_num++] = ecma_copy_value (index_value, true);
|
||||
|
||||
ECMA_FINALIZE (index_value);
|
||||
}
|
||||
|
||||
JERRY_ASSERT (copied_num == defined_prop_count || !ecma_is_completion_value_empty (ret_value));
|
||||
JERRY_ASSERT (copied_num == defined_prop_count
|
||||
|| !ecma_is_completion_value_empty (ret_value));
|
||||
|
||||
/* Sorting. */
|
||||
if (copied_num > 1 && ecma_is_completion_value_empty (ret_value))
|
||||
@ -1302,7 +1287,9 @@ ecma_builtin_array_prototype_object_sort (ecma_value_t this_arg, /**< this argum
|
||||
}
|
||||
|
||||
/* Put sorted values to the front of the array. */
|
||||
for (uint32_t index = 0; index < copied_num && ecma_is_completion_value_empty (ret_value); index++)
|
||||
for (uint32_t index = 0;
|
||||
index < copied_num && ecma_is_completion_value_empty (ret_value);
|
||||
index++)
|
||||
{
|
||||
ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index);
|
||||
ECMA_TRY_CATCH (put_value,
|
||||
@ -1312,51 +1299,41 @@ ecma_builtin_array_prototype_object_sort (ecma_value_t this_arg, /**< this argum
|
||||
ecma_deref_ecma_string (index_string_p);
|
||||
}
|
||||
|
||||
/* Undefined properties should be in the back of the array. */
|
||||
ecma_property_t *next_prop;
|
||||
for (ecma_property_t *property_p = ecma_get_property_list (obj_p);
|
||||
property_p != NULL && ecma_is_completion_value_empty (ret_value);
|
||||
property_p = next_prop)
|
||||
{
|
||||
ecma_string_t *property_name_p;
|
||||
next_prop = ECMA_GET_POINTER (ecma_property_t, property_p->next_property_p);
|
||||
|
||||
if (property_p->type == ECMA_PROPERTY_NAMEDDATA)
|
||||
{
|
||||
property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
property_p->u.named_data_property.name_p);
|
||||
}
|
||||
else if (property_p->type == ECMA_PROPERTY_NAMEDACCESSOR)
|
||||
{
|
||||
property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
property_p->u.named_accessor_property.name_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t index;
|
||||
if (ecma_string_get_array_index (property_name_p, &index) && index < len && index >= copied_num)
|
||||
{
|
||||
ECMA_TRY_CATCH (del_value, ecma_op_object_delete (obj_p, property_name_p, true), ret_value);
|
||||
ECMA_FINALIZE (del_value);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free values that were copied to the local array. */
|
||||
for (uint32_t index = 0; index < copied_num; index++)
|
||||
{
|
||||
ecma_free_value (values_buffer[index], true);
|
||||
}
|
||||
|
||||
MEM_FINALIZE_LOCAL_ARRAY (values_buffer);
|
||||
|
||||
/* Undefined properties should be in the back of the array. */
|
||||
|
||||
ecma_collection_iterator_init (&iter, array_index_props_p);
|
||||
|
||||
while (ecma_collection_iterator_next (&iter)
|
||||
&& ecma_is_completion_value_empty (ret_value))
|
||||
{
|
||||
ecma_string_t *property_name_p = ecma_get_string_from_value (*iter.current_value_p);
|
||||
|
||||
uint32_t index;
|
||||
bool is_index = ecma_string_get_array_index (property_name_p, &index);
|
||||
JERRY_ASSERT (is_index);
|
||||
|
||||
if (index >= copied_num && index < len)
|
||||
{
|
||||
ECMA_TRY_CATCH (del_value, ecma_op_object_delete (obj_p, property_name_p, true), ret_value);
|
||||
ECMA_FINALIZE (del_value);
|
||||
}
|
||||
}
|
||||
|
||||
ecma_free_values_collection (array_index_props_p, true);
|
||||
|
||||
if (ecma_is_completion_value_empty (ret_value))
|
||||
{
|
||||
ret_value = ecma_make_normal_completion_value (ecma_copy_value (this_arg, true));
|
||||
}
|
||||
|
||||
MEM_FINALIZE_LOCAL_ARRAY (values_buffer);
|
||||
|
||||
ECMA_OP_TO_NUMBER_FINALIZE (len_number);
|
||||
ECMA_FINALIZE (len_value);
|
||||
ecma_deref_ecma_string (magic_string_length_p);
|
||||
|
||||
@ -185,7 +185,7 @@ ecma_builtin_helper_get_to_locale_string_at_index (ecma_object_t *obj_p, /** < t
|
||||
|
||||
|
||||
/**
|
||||
* The Object.keys and Object.getOwnPropertyName routine's common part.
|
||||
* The Object.keys and Object.getOwnPropertyNames routine's common part.
|
||||
*
|
||||
* See also:
|
||||
* ECMA-262 v5, 15.2.3.4 steps 2-5
|
||||
@ -206,39 +206,21 @@ ecma_builtin_helper_object_get_properties (ecma_object_t *obj_p, /** < object */
|
||||
|
||||
uint32_t index = 0;
|
||||
|
||||
for (ecma_property_t *property_p = ecma_get_property_list (obj_p);
|
||||
property_p != NULL;
|
||||
property_p = ECMA_GET_POINTER (ecma_property_t, property_p->next_property_p))
|
||||
ecma_collection_header_t *props_p = ecma_op_object_get_property_names (obj_p,
|
||||
false,
|
||||
only_enumerable_properties,
|
||||
false);
|
||||
|
||||
ecma_collection_iterator_t iter;
|
||||
ecma_collection_iterator_init (&iter, props_p);
|
||||
|
||||
while (ecma_collection_iterator_next (&iter))
|
||||
{
|
||||
ecma_string_t *property_name_p;
|
||||
|
||||
if (property_p->type == ECMA_PROPERTY_NAMEDDATA)
|
||||
{
|
||||
property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
property_p->u.named_data_property.name_p);
|
||||
}
|
||||
else if (property_p->type == ECMA_PROPERTY_NAMEDACCESSOR)
|
||||
{
|
||||
property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
property_p->u.named_accessor_property.name_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (only_enumerable_properties && !ecma_is_property_enumerable (property_p))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (property_name_p != NULL);
|
||||
|
||||
ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index);
|
||||
|
||||
ecma_completion_value_t completion = ecma_builtin_helper_def_prop (new_array_p,
|
||||
index_string_p,
|
||||
ecma_make_string_value (property_name_p),
|
||||
*iter.current_value_p,
|
||||
true, /* Writable */
|
||||
true, /* Enumerable */
|
||||
true, /* Configurable */
|
||||
@ -246,12 +228,13 @@ ecma_builtin_helper_object_get_properties (ecma_object_t *obj_p, /** < object */
|
||||
|
||||
JERRY_ASSERT (ecma_is_completion_value_normal_true (completion));
|
||||
|
||||
ecma_free_completion_value (completion);
|
||||
ecma_deref_ecma_string (index_string_p);
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
ecma_free_values_collection (props_p, true);
|
||||
|
||||
return new_array;
|
||||
} /* ecma_builtin_helper_object_get_properties */
|
||||
|
||||
|
||||
@ -625,91 +625,45 @@ ecma_builtin_json_walk (ecma_object_t *reviver_p, /**< reviver function */
|
||||
{
|
||||
ecma_object_t *object_p = ecma_get_object_from_value (value_get);
|
||||
|
||||
uint32_t no_properties = 0;
|
||||
ecma_collection_header_t *props_p = ecma_op_object_get_property_names (object_p, false, true, false);
|
||||
|
||||
/*
|
||||
* The following algorithm works with arrays and objects as well.
|
||||
*/
|
||||
for (ecma_property_t *property_p = ecma_get_property_list (object_p);
|
||||
property_p != NULL;
|
||||
property_p = ECMA_GET_POINTER (ecma_property_t, property_p->next_property_p))
|
||||
ecma_collection_iterator_t iter;
|
||||
ecma_collection_iterator_init (&iter, props_p);
|
||||
|
||||
while (ecma_collection_iterator_next (&iter)
|
||||
&& ecma_is_completion_value_empty (ret_value))
|
||||
{
|
||||
ecma_string_t *property_name_p = ecma_get_string_from_value (*iter.current_value_p);
|
||||
|
||||
ECMA_TRY_CATCH (value_walk,
|
||||
ecma_builtin_json_walk (reviver_p,
|
||||
object_p,
|
||||
property_name_p),
|
||||
ret_value);
|
||||
|
||||
/*
|
||||
* All properties must be named data or internal properties, since we constructed them.
|
||||
* We cannot optimize this function since any members
|
||||
* can be changed (deleted) by the reviver function.
|
||||
*/
|
||||
JERRY_ASSERT (property_p->type == ECMA_PROPERTY_NAMEDDATA
|
||||
|| property_p->type == ECMA_PROPERTY_INTERNAL);
|
||||
|
||||
if (property_p->type == ECMA_PROPERTY_NAMEDDATA
|
||||
&& ecma_is_property_enumerable (property_p))
|
||||
if (ecma_is_value_undefined (value_walk))
|
||||
{
|
||||
no_properties++;
|
||||
ecma_completion_value_t delete_val = ecma_op_general_object_delete (object_p,
|
||||
property_name_p,
|
||||
false);
|
||||
JERRY_ASSERT (ecma_is_completion_value_normal_true (delete_val)
|
||||
|| ecma_is_completion_value_normal_false (delete_val));
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_builtin_json_define_value_property (object_p,
|
||||
property_name_p,
|
||||
value_walk);
|
||||
}
|
||||
|
||||
ECMA_FINALIZE (value_walk);
|
||||
}
|
||||
|
||||
if (no_properties > 0)
|
||||
{
|
||||
MEM_DEFINE_LOCAL_ARRAY (property_names_p, no_properties, ecma_string_t *);
|
||||
|
||||
uint32_t property_index = no_properties;
|
||||
for (ecma_property_t *property_p = ecma_get_property_list (object_p);
|
||||
property_p != NULL;
|
||||
property_p = ECMA_GET_POINTER (ecma_property_t, property_p->next_property_p))
|
||||
{
|
||||
if (property_p->type == ECMA_PROPERTY_NAMEDDATA
|
||||
&& ecma_is_property_enumerable (property_p))
|
||||
{
|
||||
ecma_string_t *property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
property_p->u.named_data_property.name_p);
|
||||
/*
|
||||
* The property list must be in creation order.
|
||||
*/
|
||||
property_index--;
|
||||
property_names_p[property_index] = ecma_copy_or_ref_ecma_string (property_name_p);
|
||||
}
|
||||
}
|
||||
|
||||
JERRY_ASSERT (property_index == 0);
|
||||
|
||||
for (property_index = 0;
|
||||
property_index < no_properties && ecma_is_completion_value_empty (ret_value);
|
||||
property_index++)
|
||||
{
|
||||
ECMA_TRY_CATCH (value_walk,
|
||||
ecma_builtin_json_walk (reviver_p,
|
||||
object_p,
|
||||
property_names_p[property_index]),
|
||||
ret_value);
|
||||
|
||||
/*
|
||||
* We cannot optimize this function since any members
|
||||
* can be changed (deleted) by the reviver function.
|
||||
*/
|
||||
if (ecma_is_value_undefined (value_walk))
|
||||
{
|
||||
ecma_completion_value_t delete_val = ecma_op_general_object_delete (object_p,
|
||||
property_names_p[property_index],
|
||||
false);
|
||||
JERRY_ASSERT (ecma_is_completion_value_normal_true (delete_val)
|
||||
|| ecma_is_completion_value_normal_false (delete_val));
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_builtin_json_define_value_property (object_p,
|
||||
property_names_p[property_index],
|
||||
value_walk);
|
||||
}
|
||||
|
||||
ECMA_FINALIZE (value_walk);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < no_properties; i++)
|
||||
{
|
||||
ecma_deref_ecma_string (property_names_p[i]);
|
||||
}
|
||||
|
||||
MEM_FINALIZE_LOCAL_ARRAY (property_names_p);
|
||||
}
|
||||
ecma_free_values_collection (props_p, true);
|
||||
}
|
||||
|
||||
if (ecma_is_completion_value_empty (ret_value))
|
||||
@ -1492,20 +1446,25 @@ ecma_builtin_json_object (ecma_object_t *obj_p, /**< the object*/
|
||||
{
|
||||
property_keys_p = ecma_new_values_collection (NULL, 0, true);
|
||||
|
||||
for (ecma_property_t *property_p = ecma_get_property_list (obj_p);
|
||||
property_p != NULL;
|
||||
property_p = ECMA_GET_POINTER (ecma_property_t, property_p->next_property_p))
|
||||
ecma_collection_header_t *props_p = ecma_op_object_get_property_names (obj_p, false, true, false);
|
||||
|
||||
ecma_collection_iterator_t iter;
|
||||
ecma_collection_iterator_init (&iter, props_p);
|
||||
|
||||
while (ecma_collection_iterator_next (&iter))
|
||||
{
|
||||
if (property_p->type == ECMA_PROPERTY_NAMEDDATA && ecma_is_property_enumerable (property_p))
|
||||
ecma_string_t *property_name_p = ecma_get_string_from_value (*iter.current_value_p);
|
||||
ecma_property_t *property_p = ecma_op_object_get_own_property (obj_p, property_name_p);
|
||||
|
||||
JERRY_ASSERT (ecma_is_property_enumerable (property_p));
|
||||
|
||||
if (property_p->type == ECMA_PROPERTY_NAMEDDATA)
|
||||
{
|
||||
ecma_string_t *prop_key = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
property_p->u.named_data_property.name_p);
|
||||
|
||||
JERRY_ASSERT (prop_key != NULL);
|
||||
|
||||
ecma_append_to_values_collection (property_keys_p, ecma_make_string_value (prop_key), true);
|
||||
ecma_append_to_values_collection (property_keys_p, *iter.current_value_p, true);
|
||||
}
|
||||
}
|
||||
|
||||
ecma_free_values_collection (props_p, true);
|
||||
}
|
||||
|
||||
/* 7. */
|
||||
|
||||
@ -199,27 +199,16 @@ ecma_builtin_object_object_seal (ecma_value_t this_arg __attr_unused___, /**< 't
|
||||
// 2.
|
||||
ecma_object_t *obj_p = ecma_get_object_from_value (arg);
|
||||
|
||||
ecma_property_t *property_p;
|
||||
for (property_p = ecma_get_property_list (obj_p);
|
||||
property_p != NULL && ecma_is_completion_value_empty (ret_value);
|
||||
property_p = ECMA_GET_POINTER (ecma_property_t, property_p->next_property_p))
|
||||
{
|
||||
ecma_string_t *property_name_p;
|
||||
ecma_collection_header_t *props_p = ecma_op_object_get_property_names (obj_p, false, false, false);
|
||||
|
||||
if (property_p->type == ECMA_PROPERTY_NAMEDDATA)
|
||||
{
|
||||
property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
property_p->u.named_data_property.name_p);
|
||||
}
|
||||
else if (property_p->type == ECMA_PROPERTY_NAMEDACCESSOR)
|
||||
{
|
||||
property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
property_p->u.named_accessor_property.name_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
ecma_collection_iterator_t iter;
|
||||
ecma_collection_iterator_init (&iter, props_p);
|
||||
|
||||
while (ecma_collection_iterator_next (&iter)
|
||||
&& ecma_is_completion_value_empty (ret_value))
|
||||
{
|
||||
ecma_string_t *property_name_p = ecma_get_string_from_value (*iter.current_value_p);
|
||||
ecma_property_t *property_p = ecma_op_object_get_own_property (obj_p, property_name_p);
|
||||
|
||||
// 2.a
|
||||
ecma_property_descriptor_t prop_desc = ecma_get_property_descriptor_from_property (property_p);
|
||||
@ -242,6 +231,8 @@ ecma_builtin_object_object_seal (ecma_value_t this_arg __attr_unused___, /**< 't
|
||||
ecma_free_property_descriptor (&prop_desc);
|
||||
}
|
||||
|
||||
ecma_free_values_collection (props_p, true);
|
||||
|
||||
if (ecma_is_completion_value_empty (ret_value))
|
||||
{
|
||||
// 3.
|
||||
@ -280,28 +271,17 @@ ecma_builtin_object_object_freeze (ecma_value_t this_arg __attr_unused___, /**<
|
||||
// 2.
|
||||
ecma_object_t *obj_p = ecma_get_object_from_value (arg);
|
||||
|
||||
ecma_property_t *property_p;
|
||||
for (property_p = ecma_get_property_list (obj_p);
|
||||
property_p != NULL && ecma_is_completion_value_empty (ret_value);
|
||||
property_p = ECMA_GET_POINTER (ecma_property_t, property_p->next_property_p))
|
||||
{
|
||||
ecma_string_t *property_name_p;
|
||||
ecma_collection_header_t *props_p = ecma_op_object_get_property_names (obj_p, false, false, false);
|
||||
|
||||
if (property_p->type == ECMA_PROPERTY_NAMEDDATA)
|
||||
{
|
||||
property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
property_p->u.named_data_property.name_p);
|
||||
}
|
||||
else
|
||||
if (property_p->type == ECMA_PROPERTY_NAMEDACCESSOR)
|
||||
{
|
||||
property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
property_p->u.named_accessor_property.name_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ecma_collection_iterator_t iter;
|
||||
ecma_collection_iterator_init (&iter, props_p);
|
||||
|
||||
while (ecma_collection_iterator_next (&iter)
|
||||
&& ecma_is_completion_value_empty (ret_value))
|
||||
{
|
||||
ecma_string_t *property_name_p = ecma_get_string_from_value (*iter.current_value_p);
|
||||
ecma_property_t *property_p = ecma_op_object_get_own_property (obj_p, property_name_p);
|
||||
|
||||
// 2.a
|
||||
ecma_property_descriptor_t prop_desc = ecma_get_property_descriptor_from_property (property_p);
|
||||
@ -330,6 +310,8 @@ ecma_builtin_object_object_freeze (ecma_value_t this_arg __attr_unused___, /**<
|
||||
ecma_free_property_descriptor (&prop_desc);
|
||||
}
|
||||
|
||||
ecma_free_values_collection (props_p, true);
|
||||
|
||||
if (ecma_is_completion_value_empty (ret_value))
|
||||
{
|
||||
// 3.
|
||||
@ -396,41 +378,45 @@ ecma_builtin_object_object_is_sealed (ecma_value_t this_arg __attr_unused___, /*
|
||||
else
|
||||
{
|
||||
ecma_object_t *obj_p = ecma_get_object_from_value (arg);
|
||||
ecma_property_t *property_p;
|
||||
|
||||
// This will be the result if the other steps doesn't change it.
|
||||
bool sealed = false;
|
||||
bool is_sealed;
|
||||
|
||||
// 3.
|
||||
// The pseudo code contains multiple early return but this way we get the same
|
||||
// result.
|
||||
if (!ecma_get_object_extensible (obj_p))
|
||||
if (ecma_get_object_extensible (obj_p))
|
||||
{
|
||||
sealed = true;
|
||||
is_sealed = false;
|
||||
}
|
||||
|
||||
// 2.
|
||||
for (property_p = ecma_get_property_list (obj_p);
|
||||
property_p != NULL && sealed;
|
||||
property_p = ECMA_GET_POINTER (ecma_property_t, property_p->next_property_p))
|
||||
else
|
||||
{
|
||||
if (property_p->type == ECMA_PROPERTY_INTERNAL)
|
||||
/* the value can be updated in the loop below */
|
||||
is_sealed = true;
|
||||
|
||||
// 2.
|
||||
ecma_collection_header_t *props_p = ecma_op_object_get_property_names (obj_p, false, false, false);
|
||||
|
||||
ecma_collection_iterator_t iter;
|
||||
ecma_collection_iterator_init (&iter, props_p);
|
||||
|
||||
while (ecma_collection_iterator_next (&iter))
|
||||
{
|
||||
continue;
|
||||
ecma_string_t *property_name_p = ecma_get_string_from_value (*iter.current_value_p);
|
||||
|
||||
// 2.a
|
||||
ecma_property_t *property_p = ecma_op_object_get_own_property (obj_p, property_name_p);
|
||||
|
||||
// 2.b
|
||||
if (ecma_is_property_configurable (property_p))
|
||||
{
|
||||
is_sealed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
JERRY_ASSERT (property_p->type == ECMA_PROPERTY_NAMEDDATA || property_p->type == ECMA_PROPERTY_NAMEDACCESSOR);
|
||||
|
||||
// 2.b
|
||||
if (ecma_is_property_configurable (property_p))
|
||||
{
|
||||
sealed = false;
|
||||
break;
|
||||
}
|
||||
ecma_free_values_collection (props_p, true);
|
||||
}
|
||||
|
||||
// 4.
|
||||
ret_value = ecma_make_simple_completion_value (sealed
|
||||
ret_value = ecma_make_simple_completion_value (is_sealed
|
||||
? ECMA_SIMPLE_VALUE_TRUE
|
||||
: ECMA_SIMPLE_VALUE_FALSE);
|
||||
}
|
||||
@ -461,48 +447,53 @@ ecma_builtin_object_object_is_frozen (ecma_value_t this_arg __attr_unused___, /*
|
||||
else
|
||||
{
|
||||
ecma_object_t *obj_p = ecma_get_object_from_value (arg);
|
||||
ecma_property_t *property_p;
|
||||
|
||||
// This will be the result if the other steps doesn't change it.
|
||||
bool frozen = false;
|
||||
bool is_frozen;
|
||||
|
||||
// 3.
|
||||
// The pseudo code contains multiple early return but this way we get the same
|
||||
// result.
|
||||
if (!ecma_get_object_extensible (obj_p))
|
||||
if (ecma_get_object_extensible (obj_p))
|
||||
{
|
||||
frozen = true;
|
||||
is_frozen = false;
|
||||
}
|
||||
|
||||
// 2.
|
||||
for (property_p = ecma_get_property_list (obj_p);
|
||||
property_p != NULL && frozen;
|
||||
property_p = ECMA_GET_POINTER (ecma_property_t, property_p->next_property_p))
|
||||
else
|
||||
{
|
||||
if (property_p->type == ECMA_PROPERTY_INTERNAL)
|
||||
is_frozen = true;
|
||||
|
||||
// 2.
|
||||
ecma_collection_header_t *props_p = ecma_op_object_get_property_names (obj_p, false, false, false);
|
||||
|
||||
ecma_collection_iterator_t iter;
|
||||
ecma_collection_iterator_init (&iter, props_p);
|
||||
|
||||
while (ecma_collection_iterator_next (&iter))
|
||||
{
|
||||
continue;
|
||||
ecma_string_t *property_name_p = ecma_get_string_from_value (*iter.current_value_p);
|
||||
|
||||
// 2.a
|
||||
ecma_property_t *property_p = ecma_op_object_get_own_property (obj_p, property_name_p);
|
||||
|
||||
JERRY_ASSERT (property_p->type == ECMA_PROPERTY_NAMEDDATA || property_p->type == ECMA_PROPERTY_NAMEDACCESSOR);
|
||||
|
||||
// 2.b
|
||||
if (property_p->type == ECMA_PROPERTY_NAMEDDATA && ecma_is_property_writable (property_p))
|
||||
{
|
||||
is_frozen = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// 2.c
|
||||
if (ecma_is_property_configurable (property_p))
|
||||
{
|
||||
is_frozen = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
JERRY_ASSERT (property_p->type == ECMA_PROPERTY_NAMEDDATA || property_p->type == ECMA_PROPERTY_NAMEDACCESSOR);
|
||||
|
||||
// 2.b
|
||||
if (property_p->type == ECMA_PROPERTY_NAMEDDATA && ecma_is_property_writable (property_p))
|
||||
{
|
||||
frozen = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// 2.c
|
||||
if (ecma_is_property_configurable (property_p))
|
||||
{
|
||||
frozen = false;
|
||||
break;
|
||||
}
|
||||
ecma_free_values_collection (props_p, true);
|
||||
}
|
||||
|
||||
// 4.
|
||||
ret_value = ecma_make_simple_completion_value (frozen
|
||||
ret_value = ecma_make_simple_completion_value (is_frozen
|
||||
? ECMA_SIMPLE_VALUE_TRUE
|
||||
: ECMA_SIMPLE_VALUE_FALSE);
|
||||
}
|
||||
@ -716,69 +707,30 @@ ecma_builtin_object_object_define_properties (ecma_value_t this_arg __attr_unuse
|
||||
ret_value);
|
||||
|
||||
ecma_object_t *props_p = ecma_get_object_from_value (props);
|
||||
ecma_property_t *property_p;
|
||||
|
||||
// First we need to know how many properties should be stored
|
||||
uint32_t property_number = 0;
|
||||
for (property_p = ecma_get_property_list (props_p);
|
||||
property_p != NULL;
|
||||
property_p = ECMA_GET_POINTER (ecma_property_t, property_p->next_property_p))
|
||||
{
|
||||
if ((property_p->type == ECMA_PROPERTY_NAMEDDATA || property_p->type == ECMA_PROPERTY_NAMEDACCESSOR)
|
||||
&& ecma_is_property_enumerable (property_p))
|
||||
{
|
||||
property_number++;
|
||||
}
|
||||
}
|
||||
|
||||
// 3.
|
||||
MEM_DEFINE_LOCAL_ARRAY (property_names_p, property_number, ecma_string_t*);
|
||||
ecma_collection_header_t *prop_names_p = ecma_op_object_get_property_names (props_p, false, true, false);
|
||||
uint32_t property_number = prop_names_p->unit_number;
|
||||
|
||||
uint32_t index = 0;
|
||||
for (property_p = ecma_get_property_list (props_p);
|
||||
property_p != NULL;
|
||||
property_p = ECMA_GET_POINTER (ecma_property_t, property_p->next_property_p))
|
||||
{
|
||||
ecma_string_t *property_name_p;
|
||||
|
||||
if (property_p->type == ECMA_PROPERTY_NAMEDDATA)
|
||||
{
|
||||
property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
property_p->u.named_data_property.name_p);
|
||||
}
|
||||
else if (property_p->type == ECMA_PROPERTY_NAMEDACCESSOR)
|
||||
{
|
||||
property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
|
||||
property_p->u.named_accessor_property.name_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ecma_is_property_enumerable (property_p))
|
||||
{
|
||||
property_names_p[index++] = ecma_copy_or_ref_ecma_string (property_name_p);
|
||||
}
|
||||
}
|
||||
ecma_collection_iterator_t iter;
|
||||
ecma_collection_iterator_init (&iter, prop_names_p);
|
||||
|
||||
// 4.
|
||||
MEM_DEFINE_LOCAL_ARRAY (property_descriptors, property_number, ecma_property_descriptor_t);
|
||||
|
||||
uint32_t property_descriptor_number = 0;
|
||||
|
||||
for (index = 0;
|
||||
index < property_number && ecma_is_completion_value_empty (ret_value);
|
||||
index++)
|
||||
while (ecma_collection_iterator_next (&iter)
|
||||
&& ecma_is_completion_value_empty (ret_value))
|
||||
{
|
||||
// 5.a
|
||||
ECMA_TRY_CATCH (desc_obj,
|
||||
ecma_op_object_get (props_p, property_names_p[index]),
|
||||
ecma_op_object_get (props_p, ecma_get_string_from_value (*iter.current_value_p)),
|
||||
ret_value);
|
||||
|
||||
// 5.b
|
||||
ECMA_TRY_CATCH (conv_result,
|
||||
ecma_op_to_property_descriptor (desc_obj,
|
||||
&property_descriptors[index]),
|
||||
&property_descriptors[property_descriptor_number]),
|
||||
ret_value);
|
||||
|
||||
property_descriptor_number++;
|
||||
@ -788,13 +740,17 @@ ecma_builtin_object_object_define_properties (ecma_value_t this_arg __attr_unuse
|
||||
}
|
||||
|
||||
// 6.
|
||||
for (index = 0;
|
||||
ecma_collection_iterator_init (&iter, prop_names_p);
|
||||
for (uint32_t index = 0;
|
||||
index < property_number && ecma_is_completion_value_empty (ret_value);
|
||||
index++)
|
||||
{
|
||||
bool is_next = ecma_collection_iterator_next (&iter);
|
||||
JERRY_ASSERT (is_next);
|
||||
|
||||
ECMA_TRY_CATCH (define_own_prop_ret,
|
||||
ecma_op_object_define_own_property (obj_p,
|
||||
property_names_p[index],
|
||||
ecma_get_string_from_value (*iter.current_value_p),
|
||||
&property_descriptors[index],
|
||||
true),
|
||||
ret_value);
|
||||
@ -803,7 +759,7 @@ ecma_builtin_object_object_define_properties (ecma_value_t this_arg __attr_unuse
|
||||
}
|
||||
|
||||
// Clean up
|
||||
for (index = 0;
|
||||
for (uint32_t index = 0;
|
||||
index < property_descriptor_number;
|
||||
index++)
|
||||
{
|
||||
@ -812,14 +768,7 @@ ecma_builtin_object_object_define_properties (ecma_value_t this_arg __attr_unuse
|
||||
|
||||
MEM_FINALIZE_LOCAL_ARRAY (property_descriptors);
|
||||
|
||||
for (index = 0;
|
||||
index < property_number;
|
||||
index++)
|
||||
{
|
||||
ecma_deref_ecma_string (property_names_p[index]);
|
||||
}
|
||||
|
||||
MEM_FINALIZE_LOCAL_ARRAY (property_names_p);
|
||||
ecma_free_values_collection (prop_names_p, true);
|
||||
|
||||
// 7.
|
||||
if (ecma_is_completion_value_empty (ret_value))
|
||||
|
||||
@ -644,7 +644,7 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */
|
||||
|
||||
uint32_t insertion_pos = 0;
|
||||
while (insertion_pos < array_index_name_pos
|
||||
&& index <= array_index_names_p[insertion_pos])
|
||||
&& index < array_index_names_p[insertion_pos])
|
||||
{
|
||||
insertion_pos++;
|
||||
}
|
||||
@ -656,6 +656,7 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */
|
||||
else
|
||||
{
|
||||
JERRY_ASSERT (insertion_pos < array_index_name_pos);
|
||||
JERRY_ASSERT (index < array_index_names_p[insertion_pos]);
|
||||
|
||||
uint32_t move_pos = ++array_index_name_pos;
|
||||
|
||||
|
||||
@ -52,15 +52,15 @@ empty_object.a = undefined;
|
||||
assert (JSON.stringify (empty_object) == '{}');
|
||||
|
||||
p_object = { "a": 1, "b": true, "c": "foo", "d": null, "e": undefined };
|
||||
assert (JSON.stringify (p_object) == '{"d":null,"c":"foo","b":true,"a":1}');
|
||||
assert (JSON.stringify (p_object) == '{"a":1,"b":true,"c":"foo","d":null}');
|
||||
|
||||
o_object = { "a": new Number(1), "b": new Boolean(true), "c": new String("foo") };
|
||||
assert (JSON.stringify (o_object) == '{"c":"foo","b":true,"a":1}');
|
||||
assert (JSON.stringify (o_object) == '{"a":1,"b":true,"c":"foo"}');
|
||||
|
||||
child = { "a": 1, "b": new String("\nfoo"), "c": undefined };
|
||||
parent = { "a": true, "b": child, "c": null};
|
||||
|
||||
assert (JSON.stringify (parent) == '{"c":null,"b":{"b":"\\nfoo","a":1},"a":true}');
|
||||
assert (JSON.stringify (parent) == '{"a":true,"b":{"a":1,"b":"\\nfoo"},"c":null}');
|
||||
|
||||
recursive_object = {};
|
||||
recursive_object.a = 2;
|
||||
@ -105,13 +105,13 @@ try {
|
||||
}
|
||||
|
||||
object = {"a": 1, "b": [1, true, {"a": "foo"}]};
|
||||
assert (JSON.stringify (object) == '{"b":[1,true,{"a":"foo"}],"a":1}');
|
||||
assert (JSON.stringify (object) == '{"a":1,"b":[1,true,{"a":"foo"}]}');
|
||||
|
||||
object = {"a": [1], "b": {}};
|
||||
assert (JSON.stringify(object) === '{"b":{},"a":[1]}');
|
||||
assert (JSON.stringify(object) === '{"a":[1],"b":{}}');
|
||||
|
||||
array = [1, {"a": 2, "b": true, c: [3]}];
|
||||
assert (JSON.stringify (array) == '[1,{"c":[3],"b":true,"a":2}]');
|
||||
assert (JSON.stringify (array) == '[1,{"a":2,"b":true,"c":[3]}]');
|
||||
|
||||
// Filtering / replacing
|
||||
to_json_object = {};
|
||||
@ -128,7 +128,7 @@ function replacer_function (key, value)
|
||||
}
|
||||
|
||||
object = { "a": "JSON", "b": new String("JSON"), "c": 3 };
|
||||
assert (JSON.stringify (object, replacer_function) == '{"c":3,"b":"JSON","a":"FOO"}');
|
||||
assert (JSON.stringify (object, replacer_function) == '{"a":"FOO","b":"JSON","c":3}');
|
||||
|
||||
filter = ["a", "b"];
|
||||
assert (JSON.stringify (object, filter) == '{"a":"JSON","b":"JSON"}');
|
||||
@ -198,7 +198,7 @@ assert (JSON.stringify (array, null, 100) == '[\n 2\n]');
|
||||
assert (JSON.stringify (array, null, -5) == '[2]');
|
||||
|
||||
nested_object = {"a": 2, "b": {"c": 1, "d": true}};
|
||||
assert (JSON.stringify (nested_object, null, 2) == '{\n "b": {\n "d": true,\n "c": 1\n },\n "a": 2\n}');
|
||||
assert (JSON.stringify (nested_object, null, 2) == '{\n "a": 2,\n "b": {\n "c": 1,\n "d": true\n }\n}');
|
||||
|
||||
nested_array = [2, [1,true]];
|
||||
assert (JSON.stringify (nested_array, null, 2) == '[\n 2,\n [\n 1,\n true\n ]\n]');
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user