Remove vm_helper_for_in_enumerate_properties_names helper; introduce ecma_op_object_get_property_names interface for building list of an object's properties.
JerryScript-DCO-1.0-Signed-off-by: Ruben Ayrapetyan r.ayrapetyan@samsung.com
This commit is contained in:
@@ -344,6 +344,9 @@ ecma_get_lex_env_outer_reference (const ecma_object_t *object_p) /**< lexical en
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get object's/lexical environment's property list.
|
* Get object's/lexical environment's property list.
|
||||||
|
*
|
||||||
|
* See also:
|
||||||
|
* ecma_op_object_get_property_names
|
||||||
*/
|
*/
|
||||||
ecma_property_t* __attr_pure___
|
ecma_property_t* __attr_pure___
|
||||||
ecma_get_property_list (const ecma_object_t *object_p) /**< object or lexical environment */
|
ecma_get_property_list (const ecma_object_t *object_p) /**< object or lexical environment */
|
||||||
@@ -362,6 +365,9 @@ ecma_get_property_list (const ecma_object_t *object_p) /**< object or lexical en
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Set object's/lexical environment's property list.
|
* Set object's/lexical environment's property list.
|
||||||
|
*
|
||||||
|
* See also:
|
||||||
|
* ecma_op_object_get_property_names
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
ecma_set_property_list (ecma_object_t *object_p, /**< object or lexical environment */
|
ecma_set_property_list (ecma_object_t *object_p, /**< object or lexical environment */
|
||||||
@@ -526,6 +532,10 @@ ecma_create_named_data_property (ecma_object_t *obj_p, /**< object */
|
|||||||
|
|
||||||
ecma_set_named_data_property_value (prop_p, ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED));
|
ecma_set_named_data_property_value (prop_p, ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See also:
|
||||||
|
* ecma_op_object_get_property_names
|
||||||
|
*/
|
||||||
ecma_property_t *list_head_p = ecma_get_property_list (obj_p);
|
ecma_property_t *list_head_p = ecma_get_property_list (obj_p);
|
||||||
ECMA_SET_POINTER (prop_p->next_property_p, list_head_p);
|
ECMA_SET_POINTER (prop_p->next_property_p, list_head_p);
|
||||||
ecma_set_property_list (obj_p, prop_p);
|
ecma_set_property_list (obj_p, prop_p);
|
||||||
@@ -568,6 +578,10 @@ ecma_create_named_accessor_property (ecma_object_t *obj_p, /**< object */
|
|||||||
|
|
||||||
ECMA_SET_NON_NULL_POINTER (prop_p->u.named_accessor_property.getter_setter_pair_cp, getter_setter_pointers_p);
|
ECMA_SET_NON_NULL_POINTER (prop_p->u.named_accessor_property.getter_setter_pair_cp, getter_setter_pointers_p);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See also:
|
||||||
|
* ecma_op_object_get_property_names
|
||||||
|
*/
|
||||||
ecma_property_t *list_head_p = ecma_get_property_list (obj_p);
|
ecma_property_t *list_head_p = ecma_get_property_list (obj_p);
|
||||||
ECMA_SET_POINTER (prop_p->next_property_p, list_head_p);
|
ECMA_SET_POINTER (prop_p->next_property_p, list_head_p);
|
||||||
ecma_set_property_list (obj_p, prop_p);
|
ecma_set_property_list (obj_p, prop_p);
|
||||||
|
|||||||
@@ -518,6 +518,273 @@ ecma_op_object_is_prototype_of (ecma_object_t *base_p, /** < base object */
|
|||||||
} while (true);
|
} while (true);
|
||||||
} /* ecma_op_object_is_prototype_of */
|
} /* ecma_op_object_is_prototype_of */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get collection of property names
|
||||||
|
*
|
||||||
|
* Order of names in the collection:
|
||||||
|
* - integer indices in ascending order
|
||||||
|
* - other indices in creation order (for built-ins - in the order the properties are listed in specification).
|
||||||
|
*
|
||||||
|
* Note:
|
||||||
|
* Implementation of the routine assumes that new properties are appended to beginning of corresponding object's
|
||||||
|
* property list, and the list is not reordered (in other words, properties are stored in order that is reversed
|
||||||
|
* to the properties' addition order).
|
||||||
|
*
|
||||||
|
* @return collection of strings - property names
|
||||||
|
*/
|
||||||
|
ecma_collection_header_t *
|
||||||
|
ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */
|
||||||
|
bool is_array_indices_only, /**< true - exclude properties with names
|
||||||
|
* that are not indices */
|
||||||
|
bool is_enumerable_only, /**< true - exclude non-enumerable properties */
|
||||||
|
bool is_with_prototype_chain) /**< true - list properties from prototype chain,
|
||||||
|
* false - list only own properties */
|
||||||
|
{
|
||||||
|
ecma_collection_header_t *ret_p = ecma_new_strings_collection (NULL, 0);
|
||||||
|
ecma_collection_header_t *skipped_non_enumerable_p = ecma_new_strings_collection (NULL, 0);
|
||||||
|
|
||||||
|
const size_t bitmap_row_size = sizeof (uint32_t) * JERRY_BITSINBYTE;
|
||||||
|
uint32_t names_hashes_bitmap[(1u << LIT_STRING_HASH_BITS) / bitmap_row_size];
|
||||||
|
|
||||||
|
memset (names_hashes_bitmap, 0, sizeof (names_hashes_bitmap));
|
||||||
|
|
||||||
|
for (ecma_object_t *prototype_chain_iter_p = obj_p;
|
||||||
|
prototype_chain_iter_p != NULL;
|
||||||
|
prototype_chain_iter_p = is_with_prototype_chain ? ecma_get_object_prototype (prototype_chain_iter_p)
|
||||||
|
: NULL)
|
||||||
|
{
|
||||||
|
ecma_length_t string_named_properties_count = 0;
|
||||||
|
ecma_length_t array_index_named_properties_count = 0;
|
||||||
|
ecma_length_t skipped_non_enumerable_properties_count = 0;
|
||||||
|
|
||||||
|
/* First pass: counting properties */
|
||||||
|
for (ecma_property_t *prop_iter_p = ecma_get_property_list (prototype_chain_iter_p);
|
||||||
|
prop_iter_p != NULL;
|
||||||
|
prop_iter_p = ECMA_GET_POINTER (ecma_property_t, prop_iter_p->next_property_p))
|
||||||
|
{
|
||||||
|
if (prop_iter_p->type == ECMA_PROPERTY_NAMEDDATA
|
||||||
|
|| prop_iter_p->type == ECMA_PROPERTY_NAMEDACCESSOR)
|
||||||
|
{
|
||||||
|
ecma_string_t *name_p;
|
||||||
|
|
||||||
|
if (prop_iter_p->type == ECMA_PROPERTY_NAMEDDATA)
|
||||||
|
{
|
||||||
|
name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, prop_iter_p->u.named_data_property.name_p);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
JERRY_ASSERT (prop_iter_p->type == ECMA_PROPERTY_NAMEDACCESSOR);
|
||||||
|
|
||||||
|
name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, prop_iter_p->u.named_accessor_property.name_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(is_enumerable_only && !ecma_is_property_enumerable (prop_iter_p)))
|
||||||
|
{
|
||||||
|
uint32_t index;
|
||||||
|
|
||||||
|
if (ecma_string_get_array_index (name_p, &index))
|
||||||
|
{
|
||||||
|
/* name_p is a valid array index */
|
||||||
|
array_index_named_properties_count++;
|
||||||
|
}
|
||||||
|
else if (!is_array_indices_only)
|
||||||
|
{
|
||||||
|
string_named_properties_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
JERRY_ASSERT (is_enumerable_only && !ecma_is_property_enumerable (prop_iter_p));
|
||||||
|
|
||||||
|
skipped_non_enumerable_properties_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
JERRY_ASSERT (prop_iter_p->type == ECMA_PROPERTY_INTERNAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Second pass: collecting properties names into arrays */
|
||||||
|
MEM_DEFINE_LOCAL_ARRAY (names_p,
|
||||||
|
array_index_named_properties_count + string_named_properties_count,
|
||||||
|
ecma_string_t *);
|
||||||
|
MEM_DEFINE_LOCAL_ARRAY (array_index_names_p, array_index_named_properties_count, uint32_t);
|
||||||
|
|
||||||
|
uint32_t name_pos = array_index_named_properties_count + string_named_properties_count;
|
||||||
|
uint32_t array_index_name_pos = 0;
|
||||||
|
|
||||||
|
for (ecma_property_t *prop_iter_p = ecma_get_property_list (prototype_chain_iter_p);
|
||||||
|
prop_iter_p != NULL;
|
||||||
|
prop_iter_p = ECMA_GET_POINTER (ecma_property_t, prop_iter_p->next_property_p))
|
||||||
|
{
|
||||||
|
if (prop_iter_p->type == ECMA_PROPERTY_NAMEDDATA
|
||||||
|
|| prop_iter_p->type == ECMA_PROPERTY_NAMEDACCESSOR)
|
||||||
|
{
|
||||||
|
ecma_string_t *name_p;
|
||||||
|
|
||||||
|
if (prop_iter_p->type == ECMA_PROPERTY_NAMEDDATA)
|
||||||
|
{
|
||||||
|
name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, prop_iter_p->u.named_data_property.name_p);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
JERRY_ASSERT (prop_iter_p->type == ECMA_PROPERTY_NAMEDACCESSOR);
|
||||||
|
|
||||||
|
name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, prop_iter_p->u.named_accessor_property.name_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(is_enumerable_only && !ecma_is_property_enumerable (prop_iter_p)))
|
||||||
|
{
|
||||||
|
uint32_t index;
|
||||||
|
|
||||||
|
if (ecma_string_get_array_index (name_p, &index))
|
||||||
|
{
|
||||||
|
JERRY_ASSERT (array_index_name_pos < array_index_named_properties_count);
|
||||||
|
|
||||||
|
uint32_t insertion_pos = 0;
|
||||||
|
while (insertion_pos < array_index_name_pos
|
||||||
|
&& index <= array_index_names_p[insertion_pos])
|
||||||
|
{
|
||||||
|
insertion_pos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (insertion_pos == array_index_name_pos)
|
||||||
|
{
|
||||||
|
array_index_names_p[array_index_name_pos++] = index;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
JERRY_ASSERT (insertion_pos < array_index_name_pos);
|
||||||
|
|
||||||
|
uint32_t move_pos = ++array_index_name_pos;
|
||||||
|
|
||||||
|
while (move_pos != insertion_pos)
|
||||||
|
{
|
||||||
|
array_index_names_p[move_pos] = array_index_names_p[move_pos - 1u];
|
||||||
|
|
||||||
|
move_pos--;
|
||||||
|
}
|
||||||
|
|
||||||
|
array_index_names_p[insertion_pos] = index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!is_array_indices_only)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Filling from end to begin, as list of object's properties is sorted
|
||||||
|
* in order that is reverse to properties creation order
|
||||||
|
*/
|
||||||
|
|
||||||
|
JERRY_ASSERT (name_pos > 0
|
||||||
|
&& name_pos <= array_index_named_properties_count + string_named_properties_count);
|
||||||
|
names_p[--name_pos] = ecma_copy_or_ref_ecma_string (name_p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
JERRY_ASSERT (is_enumerable_only && !ecma_is_property_enumerable (prop_iter_p));
|
||||||
|
|
||||||
|
ecma_append_to_values_collection (skipped_non_enumerable_p,
|
||||||
|
ecma_make_string_value (name_p),
|
||||||
|
true);
|
||||||
|
|
||||||
|
lit_string_hash_t hash = name_p->hash;
|
||||||
|
uint32_t bitmap_row = hash / bitmap_row_size;
|
||||||
|
uint32_t bitmap_column = hash % bitmap_row_size;
|
||||||
|
|
||||||
|
if ((names_hashes_bitmap[bitmap_row] & (1u << bitmap_column)) == 0)
|
||||||
|
{
|
||||||
|
names_hashes_bitmap[bitmap_row] |= (1u << bitmap_column);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
JERRY_ASSERT (prop_iter_p->type == ECMA_PROPERTY_INTERNAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < array_index_named_properties_count; i++)
|
||||||
|
{
|
||||||
|
JERRY_ASSERT (name_pos > 0
|
||||||
|
&& name_pos <= array_index_named_properties_count + string_named_properties_count);
|
||||||
|
names_p[--name_pos] = ecma_new_ecma_string_from_uint32 (array_index_names_p[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
JERRY_ASSERT (name_pos == 0);
|
||||||
|
|
||||||
|
MEM_FINALIZE_LOCAL_ARRAY (array_index_names_p);
|
||||||
|
|
||||||
|
for (uint32_t i = 0;
|
||||||
|
i < array_index_named_properties_count + string_named_properties_count;
|
||||||
|
i++)
|
||||||
|
{
|
||||||
|
bool is_append;
|
||||||
|
|
||||||
|
ecma_string_t *name_p = names_p[i];
|
||||||
|
|
||||||
|
lit_string_hash_t hash = name_p->hash;
|
||||||
|
uint32_t bitmap_row = hash / bitmap_row_size;
|
||||||
|
uint32_t bitmap_column = hash % bitmap_row_size;
|
||||||
|
|
||||||
|
if ((names_hashes_bitmap[bitmap_row] & (1u << bitmap_column)) == 0)
|
||||||
|
{
|
||||||
|
/* no name with the hash is in constructed collection */
|
||||||
|
is_append = true;
|
||||||
|
|
||||||
|
names_hashes_bitmap[bitmap_row] |= (1u << bitmap_column);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* name with same hash already occured */
|
||||||
|
bool is_equal_found = false;
|
||||||
|
|
||||||
|
ecma_collection_iterator_t iter;
|
||||||
|
ecma_collection_iterator_init (&iter, ret_p);
|
||||||
|
|
||||||
|
while (ecma_collection_iterator_next (&iter))
|
||||||
|
{
|
||||||
|
ecma_string_t *iter_name_p = ecma_get_string_from_value (*iter.current_value_p);
|
||||||
|
|
||||||
|
if (ecma_compare_ecma_strings (name_p, iter_name_p))
|
||||||
|
{
|
||||||
|
is_equal_found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ecma_collection_iterator_init (&iter, skipped_non_enumerable_p);
|
||||||
|
while (ecma_collection_iterator_next (&iter))
|
||||||
|
{
|
||||||
|
ecma_string_t *iter_name_p = ecma_get_string_from_value (*iter.current_value_p);
|
||||||
|
|
||||||
|
if (ecma_compare_ecma_strings (name_p, iter_name_p))
|
||||||
|
{
|
||||||
|
is_equal_found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
is_append = !is_equal_found;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_append)
|
||||||
|
{
|
||||||
|
JERRY_ASSERT ((names_hashes_bitmap[bitmap_row] & (1u << bitmap_column)) != 0);
|
||||||
|
|
||||||
|
ecma_append_to_values_collection (ret_p, ecma_make_string_value (names_p[i]), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
ecma_deref_ecma_string (name_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_FINALIZE_LOCAL_ARRAY (names_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
ecma_free_values_collection (skipped_non_enumerable_p, true);
|
||||||
|
|
||||||
|
return ret_p;
|
||||||
|
} /* ecma_op_object_get_property_names */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get [[Class]] string of specified object
|
* Get [[Class]] string of specified object
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ extern ecma_completion_value_t
|
|||||||
ecma_op_object_define_own_property (ecma_object_t *, ecma_string_t *, const ecma_property_descriptor_t *, bool);
|
ecma_op_object_define_own_property (ecma_object_t *, ecma_string_t *, const ecma_property_descriptor_t *, bool);
|
||||||
extern ecma_completion_value_t ecma_op_object_has_instance (ecma_object_t *, ecma_value_t);
|
extern ecma_completion_value_t ecma_op_object_has_instance (ecma_object_t *, ecma_value_t);
|
||||||
extern bool ecma_op_object_is_prototype_of (ecma_object_t *, ecma_object_t *);
|
extern bool ecma_op_object_is_prototype_of (ecma_object_t *, ecma_object_t *);
|
||||||
|
extern ecma_collection_header_t * ecma_op_object_get_property_names (ecma_object_t *, bool, bool, bool);
|
||||||
|
|
||||||
extern lit_magic_string_id_t ecma_object_get_class_name (ecma_object_t *);
|
extern lit_magic_string_id_t ecma_object_get_class_name (ecma_object_t *);
|
||||||
|
|
||||||
|
|||||||
@@ -17,161 +17,6 @@
|
|||||||
#include "opcodes.h"
|
#include "opcodes.h"
|
||||||
#include "opcodes-ecma-support.h"
|
#include "opcodes-ecma-support.h"
|
||||||
|
|
||||||
/**
|
|
||||||
* Enumerate properties and construct collection with their
|
|
||||||
* names for further iteration in for-in opcode handler.
|
|
||||||
*
|
|
||||||
* See also:
|
|
||||||
* ECMA-262 v5, 12.6.4
|
|
||||||
*
|
|
||||||
* @return header of constructed strings collection (should be freed with ecma_free_values_collection),
|
|
||||||
* or NULL - if there are no properties to enumerate in for-in.
|
|
||||||
*/
|
|
||||||
static ecma_collection_header_t *
|
|
||||||
vm_helper_for_in_enumerate_properties_names (ecma_object_t *obj_p) /**< starting object - result of ToObject
|
|
||||||
* conversion (ECMA-262 v5, 12.6.4, step 4) */
|
|
||||||
{
|
|
||||||
const size_t bitmap_row_size = sizeof (uint32_t) * JERRY_BITSINBYTE;
|
|
||||||
uint32_t names_hashes_bitmap[(1u << LIT_STRING_HASH_BITS) / bitmap_row_size];
|
|
||||||
|
|
||||||
memset (names_hashes_bitmap, 0, sizeof (names_hashes_bitmap));
|
|
||||||
|
|
||||||
ecma_length_t all_properties_count = 0;
|
|
||||||
|
|
||||||
/* First pass: counting properties */
|
|
||||||
for (ecma_object_t *prototype_chain_iter_p = obj_p;
|
|
||||||
prototype_chain_iter_p != NULL;
|
|
||||||
prototype_chain_iter_p = ecma_get_object_prototype (prototype_chain_iter_p))
|
|
||||||
{
|
|
||||||
for (ecma_property_t *prop_iter_p = ecma_get_property_list (prototype_chain_iter_p);
|
|
||||||
prop_iter_p != NULL;
|
|
||||||
prop_iter_p = ECMA_GET_POINTER (ecma_property_t, prop_iter_p->next_property_p))
|
|
||||||
{
|
|
||||||
if (prop_iter_p->type == ECMA_PROPERTY_NAMEDDATA
|
|
||||||
|| prop_iter_p->type == ECMA_PROPERTY_NAMEDACCESSOR)
|
|
||||||
{
|
|
||||||
all_properties_count++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
JERRY_ASSERT (prop_iter_p->type == ECMA_PROPERTY_INTERNAL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (all_properties_count == 0)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ecma_collection_header_t *ret_p = NULL;
|
|
||||||
|
|
||||||
/* Second pass: collecting properties names */
|
|
||||||
MEM_DEFINE_LOCAL_ARRAY (names_p, all_properties_count, ecma_string_t*);
|
|
||||||
|
|
||||||
ecma_length_t enumerated_properties_count = 0;
|
|
||||||
ecma_length_t non_enumerated_properties_count = 0;
|
|
||||||
|
|
||||||
for (ecma_object_t *prototype_chain_iter_p = obj_p;
|
|
||||||
prototype_chain_iter_p != NULL;
|
|
||||||
prototype_chain_iter_p = ecma_get_object_prototype (prototype_chain_iter_p))
|
|
||||||
{
|
|
||||||
for (ecma_property_t *prop_iter_p = ecma_get_property_list (prototype_chain_iter_p);
|
|
||||||
prop_iter_p != NULL;
|
|
||||||
prop_iter_p = ECMA_GET_POINTER (ecma_property_t, prop_iter_p->next_property_p))
|
|
||||||
{
|
|
||||||
if (prop_iter_p->type == ECMA_PROPERTY_NAMEDDATA
|
|
||||||
|| prop_iter_p->type == ECMA_PROPERTY_NAMEDACCESSOR)
|
|
||||||
{
|
|
||||||
bool is_enumerated;
|
|
||||||
|
|
||||||
ecma_string_t *prop_name_p;
|
|
||||||
|
|
||||||
if (prop_iter_p->type == ECMA_PROPERTY_NAMEDDATA)
|
|
||||||
{
|
|
||||||
prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, prop_iter_p->u.named_data_property.name_p);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, prop_iter_p->u.named_accessor_property.name_p);
|
|
||||||
}
|
|
||||||
|
|
||||||
lit_string_hash_t hash = prop_name_p->hash;
|
|
||||||
uint32_t bitmap_row = hash / bitmap_row_size;
|
|
||||||
uint32_t bitmap_column = hash % bitmap_row_size;
|
|
||||||
|
|
||||||
if (ecma_is_property_enumerable (prop_iter_p))
|
|
||||||
{
|
|
||||||
if ((names_hashes_bitmap[bitmap_row] & (1u << bitmap_column)) == 0)
|
|
||||||
{
|
|
||||||
/* no name with the hash occured during the iteration session */
|
|
||||||
is_enumerated = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* name with same hash already occured */
|
|
||||||
bool is_equal_found = false;
|
|
||||||
|
|
||||||
for (uint32_t index = 0;
|
|
||||||
!is_equal_found && index < enumerated_properties_count;
|
|
||||||
index++)
|
|
||||||
{
|
|
||||||
if (ecma_compare_ecma_strings (prop_name_p,
|
|
||||||
names_p[index]))
|
|
||||||
{
|
|
||||||
is_equal_found = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint32_t index = 0;
|
|
||||||
!is_equal_found && index < non_enumerated_properties_count;
|
|
||||||
index++)
|
|
||||||
{
|
|
||||||
if (ecma_compare_ecma_strings (prop_name_p,
|
|
||||||
names_p[all_properties_count - index - 1]))
|
|
||||||
{
|
|
||||||
is_equal_found = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
is_enumerated = !is_equal_found;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
is_enumerated = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
names_hashes_bitmap[bitmap_row] |= (1u << bitmap_column);
|
|
||||||
|
|
||||||
if (is_enumerated)
|
|
||||||
{
|
|
||||||
names_p[enumerated_properties_count++] = prop_name_p;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
names_p[all_properties_count - non_enumerated_properties_count++ - 1] = prop_name_p;
|
|
||||||
}
|
|
||||||
|
|
||||||
JERRY_ASSERT (enumerated_properties_count + non_enumerated_properties_count <= all_properties_count);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
JERRY_ASSERT (prop_iter_p->type == ECMA_PROPERTY_INTERNAL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enumerated_properties_count != 0)
|
|
||||||
{
|
|
||||||
ret_p = ecma_new_strings_collection (names_p, enumerated_properties_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
MEM_FINALIZE_LOCAL_ARRAY (names_p);
|
|
||||||
|
|
||||||
return ret_p;
|
|
||||||
} /* vm_helper_for_in_enumerate_properties_names */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 'for-in' opcode handler
|
* 'for-in' opcode handler
|
||||||
*
|
*
|
||||||
@@ -219,7 +64,7 @@ opfunc_for_in (vm_instr_t instr, /**< instruction */
|
|||||||
ecma_object_t *obj_p = ecma_get_object_from_value (obj_expr_value);
|
ecma_object_t *obj_p = ecma_get_object_from_value (obj_expr_value);
|
||||||
|
|
||||||
ecma_collection_iterator_t names_iterator;
|
ecma_collection_iterator_t names_iterator;
|
||||||
ecma_collection_header_t *names_p = vm_helper_for_in_enumerate_properties_names (obj_p);
|
ecma_collection_header_t *names_p = ecma_op_object_get_property_names (obj_p, false, true, true);
|
||||||
|
|
||||||
if (names_p != NULL)
|
if (names_p != NULL)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user