diff --git a/jerry-core/ecma/base/ecma-globals.h b/jerry-core/ecma/base/ecma-globals.h index ed5df15bd..5d3718376 100644 --- a/jerry-core/ecma/base/ecma-globals.h +++ b/jerry-core/ecma/base/ecma-globals.h @@ -335,9 +335,10 @@ typedef enum ECMA_LIST_ENUMERABLE = (1 << 1), /**< exclude non-enumerable properties */ ECMA_LIST_PROTOTYPE = (1 << 2), /**< list properties from prototype chain */ #if ENABLED (JERRY_ES2015) - ECMA_LIST_SYMBOLS = (1 << 3), /**< list symbol properties only */ + ECMA_LIST_SYMBOLS = (1 << 3), /**< list symbol properties */ + ECMA_LIST_SYMBOLS_ONLY = (1 << 4), /**< list symbol properties only */ #endif /* ENABLED (JERRY_ES2015) */ - ECMA_LIST_CONVERT_FAST_ARRAYS = (1 << 4), /**< after listing the properties convert + ECMA_LIST_CONVERT_FAST_ARRAYS = (1 << 5), /**< after listing the properties convert * the fast access mode array back to normal array */ } ecma_list_properties_options_t; diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-object.c b/jerry-core/ecma/builtin-objects/ecma-builtin-object.c index bf9579f7f..1b536b951 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-object.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-object.c @@ -290,7 +290,7 @@ ecma_builtin_object_object_get_own_property_names (ecma_object_t *obj_p) /**< ro static ecma_value_t ecma_builtin_object_object_get_own_property_symbols (ecma_object_t *obj_p) /**< routine's argument */ { - return ecma_builtin_helper_object_get_properties (obj_p, ECMA_LIST_SYMBOLS); + return ecma_builtin_helper_object_get_properties (obj_p, ECMA_LIST_SYMBOLS_ONLY); } /* ecma_builtin_object_object_get_own_property_symbols */ #endif /* ENABLED (JERRY_ES2015) */ @@ -781,15 +781,15 @@ ecma_builtin_object_object_assign (ecma_object_t *target_p, /**< target object * ecma_object_t *from_obj_p = ecma_get_object_from_value (from_value); /* 5.b.iii */ - /* TODO: extends this collection if symbols will be supported */ ecma_collection_t *props_p = ecma_op_object_get_property_names (from_obj_p, ECMA_LIST_CONVERT_FAST_ARRAYS - | ECMA_LIST_ENUMERABLE); + | ECMA_LIST_ENUMERABLE + | ECMA_LIST_SYMBOLS); ecma_value_t *buffer_p = props_p->buffer_p; for (uint32_t j = 0; (j < props_p->item_count) && ecma_is_value_empty (ret_value); j++) { - ecma_string_t *property_name_p = ecma_get_string_from_value (buffer_p[j]); + ecma_string_t *property_name_p = ecma_get_prop_name_from_value (buffer_p[j]); /* 5.c.i-ii */ ecma_property_descriptor_t prop_desc; diff --git a/jerry-core/ecma/builtin-objects/ecma-builtins.c b/jerry-core/ecma/builtin-objects/ecma-builtins.c index ff450b5a0..dd4734173 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtins.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtins.c @@ -897,18 +897,17 @@ ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object * */ void ecma_builtin_list_lazy_property_names (ecma_object_t *object_p, /**< a built-in object */ - bool separate_enumerable, /**< true - list enumerable properties into - * main collection, and non-enumerable - * to collection of 'skipped non-enumerable' - * properties, - * false - list all properties into main collection. - */ + uint32_t opts, /**< listing options using flags + * from ecma_list_properties_options_t */ ecma_collection_t *main_collection_p, /**< 'main' collection */ ecma_collection_t *non_enum_collection_p) /**< skipped 'non-enumerable' * collection */ { JERRY_ASSERT (ecma_get_object_is_builtin (object_p)); + const bool separate_enumerable = (opts & ECMA_LIST_ENUMERABLE) != 0; + const bool is_array_indices_only = (opts & ECMA_LIST_ARRAY_INDICES) != 0; + if (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_FUNCTION && ecma_builtin_function_is_routine (object_p)) { @@ -966,6 +965,12 @@ ecma_builtin_list_lazy_property_names (ecma_object_t *object_p, /**< a built-in ecma_string_t *name_p = ecma_get_magic_string ((lit_magic_string_id_t) curr_property_p->magic_string_id); + if (is_array_indices_only && ecma_string_get_array_index (name_p) == ECMA_STRING_NOT_ARRAY_INDEX) + { + curr_property_p++; + continue; + } + uint32_t bit_for_index = (uint32_t) 1u << index; if (!(*bitset_p & bit_for_index) || ecma_op_object_has_own_property (object_p, name_p)) diff --git a/jerry-core/ecma/builtin-objects/ecma-builtins.h b/jerry-core/ecma/builtin-objects/ecma-builtins.h index 15d21c42e..6d0228cde 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtins.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtins.h @@ -91,7 +91,7 @@ ecma_property_t * ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, ecma_string_t *string_p); void ecma_builtin_list_lazy_property_names (ecma_object_t *object_p, - bool separate_enumerable, + uint32_t opts, ecma_collection_t *main_collection_p, ecma_collection_t *non_enum_collection_p); bool diff --git a/jerry-core/ecma/operations/ecma-array-object.c b/jerry-core/ecma/operations/ecma-array-object.c index 04eb9d2f3..ad538ba8f 100644 --- a/jerry-core/ecma/operations/ecma-array-object.c +++ b/jerry-core/ecma/operations/ecma-array-object.c @@ -508,7 +508,7 @@ ecma_fast_array_get_property_names (ecma_object_t *object_p, /**< fast access mo ecma_collection_t *ret_p = ecma_new_collection (); #if ENABLED (JERRY_ES2015) - if (opts & ECMA_LIST_SYMBOLS) + if (opts & ECMA_LIST_SYMBOLS_ONLY) { return ret_p; } @@ -1185,13 +1185,8 @@ ecma_array_get_length (ecma_object_t *array_p) /**< array object */ */ void ecma_op_array_list_lazy_property_names (ecma_object_t *obj_p, /**< a String object */ - bool separate_enumerable, /**< true - list enumerable properties - * into main collection, - * and non-enumerable to collection of - * 'skipped non-enumerable' properties, - * false - list all properties into main - * collection. - */ + uint32_t opts, /**< listing options using flags + * from ecma_list_properties_options_t */ ecma_collection_t *main_collection_p, /**< 'main' collection */ ecma_collection_t *non_enum_collection_p) /**< skipped * 'non-enumerable' @@ -1199,9 +1194,12 @@ ecma_op_array_list_lazy_property_names (ecma_object_t *obj_p, /**< a String obje { JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_ARRAY); - ecma_collection_t *for_non_enumerable_p = separate_enumerable ? non_enum_collection_p : main_collection_p; + ecma_collection_t *for_non_enumerable_p = (opts & ECMA_LIST_ENUMERABLE) ? non_enum_collection_p : main_collection_p; - ecma_collection_push_back (for_non_enumerable_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); + if ((opts & ECMA_LIST_ARRAY_INDICES) == 0) + { + ecma_collection_push_back (for_non_enumerable_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); + } } /* ecma_op_array_list_lazy_property_names */ /** diff --git a/jerry-core/ecma/operations/ecma-array-object.h b/jerry-core/ecma/operations/ecma-array-object.h index 7a6fde10c..24667373b 100644 --- a/jerry-core/ecma/operations/ecma-array-object.h +++ b/jerry-core/ecma/operations/ecma-array-object.h @@ -117,7 +117,8 @@ ecma_op_array_object_define_own_property (ecma_object_t *object_p, ecma_string_t uint32_t ecma_array_get_length (ecma_object_t *array_p); void -ecma_op_array_list_lazy_property_names (ecma_object_t *obj_p, bool separate_enumerable, +ecma_op_array_list_lazy_property_names (ecma_object_t *obj_p, + uint32_t opts, ecma_collection_t *main_collection_p, ecma_collection_t *non_enum_collection_p); diff --git a/jerry-core/ecma/operations/ecma-function-object.c b/jerry-core/ecma/operations/ecma-function-object.c index 7539f9d61..77ea4be41 100644 --- a/jerry-core/ecma/operations/ecma-function-object.c +++ b/jerry-core/ecma/operations/ecma-function-object.c @@ -1770,13 +1770,8 @@ ecma_op_bound_function_try_to_lazy_instantiate_property (ecma_object_t *object_p */ void ecma_op_function_list_lazy_property_names (ecma_object_t *object_p, /**< functionobject */ - bool separate_enumerable, /**< true - list enumerable properties into - * main collection and non-enumerable - * to collection of 'skipped - * non-enumerable' properties, - * false - list all properties into main - * collection. - */ + uint32_t opts, /**< listing options using flags + * from ecma_list_properties_options_t */ ecma_collection_t *main_collection_p, /**< 'main' collection */ ecma_collection_t *non_enum_collection_p) /**< skipped * 'non-enumerable' @@ -1784,7 +1779,7 @@ ecma_op_function_list_lazy_property_names (ecma_object_t *object_p, /**< functio { JERRY_UNUSED (main_collection_p); - ecma_collection_t *for_non_enumerable_p = separate_enumerable ? non_enum_collection_p : main_collection_p; + ecma_collection_t *for_non_enumerable_p = (opts & ECMA_LIST_ENUMERABLE) ? non_enum_collection_p : main_collection_p; /* 'length' property is non-enumerable (ECMA-262 v5, 13.2.5) */ ecma_collection_push_back (for_non_enumerable_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); @@ -1825,21 +1820,15 @@ ecma_op_function_list_lazy_property_names (ecma_object_t *object_p, /**< functio * ecma_op_external_function_try_to_lazy_instantiate_property */ void -ecma_op_external_function_list_lazy_property_names (bool separate_enumerable, /**< true - list enumerable properties - * into main collection and - * non-enumerable to collection - * of 'skipped non-enumerable' - * properties, - * false - list all properties into - * main collection. - */ - ecma_collection_t *main_collection_p, /**< 'main' collection */ - ecma_collection_t *non_enum_collection_p) /**< skipped - * collection */ +ecma_op_external_function_list_lazy_property_names (uint32_t opts, /**< listing options using flags + * from ecma_list_properties_options_t */ + ecma_collection_t *main_collection_p, /**< 'main' collection */ + ecma_collection_t *non_enum_collection_p) /**< skipped + * collection */ { JERRY_UNUSED (main_collection_p); - ecma_collection_t *for_non_enumerable_p = separate_enumerable ? non_enum_collection_p : main_collection_p; + ecma_collection_t *for_non_enumerable_p = (opts & ECMA_LIST_ENUMERABLE) ? non_enum_collection_p : main_collection_p; /* 'prototype' property is non-enumerable (ECMA-262 v5, 13.2.18) */ ecma_collection_push_back (for_non_enumerable_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_PROTOTYPE)); @@ -1853,14 +1842,8 @@ ecma_op_external_function_list_lazy_property_names (bool separate_enumerable, /* * ecma_op_bound_function_try_to_lazy_instantiate_property */ void -ecma_op_bound_function_list_lazy_property_names (bool separate_enumerable, /**< true - list enumerable properties - * into main collection and - * non-enumerable to collection - * of 'skipped non-enumerable' - * properties, - * false - list all properties into - * main collection. - */ +ecma_op_bound_function_list_lazy_property_names (uint32_t opts, /**< listing options using flags + * from ecma_list_properties_options_t */ ecma_collection_t *main_collection_p, /**< 'main' collection */ ecma_collection_t *non_enum_collection_p) /**< skipped * 'non-enumerable' @@ -1868,7 +1851,7 @@ ecma_op_bound_function_list_lazy_property_names (bool separate_enumerable, /**< { JERRY_UNUSED (main_collection_p); - ecma_collection_t *for_non_enumerable_p = separate_enumerable ? non_enum_collection_p : main_collection_p; + ecma_collection_t *for_non_enumerable_p = (opts & ECMA_LIST_ENUMERABLE) ? non_enum_collection_p : main_collection_p; /* 'length' property is non-enumerable (ECMA-262 v5, 13.2.5) */ ecma_collection_push_back (for_non_enumerable_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); diff --git a/jerry-core/ecma/operations/ecma-function-object.h b/jerry-core/ecma/operations/ecma-function-object.h index b7dc12102..92b1d6cc7 100644 --- a/jerry-core/ecma/operations/ecma-function-object.h +++ b/jerry-core/ecma/operations/ecma-function-object.h @@ -110,17 +110,17 @@ ecma_op_bound_function_try_to_lazy_instantiate_property (ecma_object_t *object_p void ecma_op_function_list_lazy_property_names (ecma_object_t *object_p, - bool separate_enumerable, + uint32_t opts, ecma_collection_t *main_collection_p, ecma_collection_t *non_enum_collection_p); void -ecma_op_external_function_list_lazy_property_names (bool separate_enumerable, +ecma_op_external_function_list_lazy_property_names (uint32_t opts, ecma_collection_t *main_collection_p, ecma_collection_t *non_enum_collection_p); void -ecma_op_bound_function_list_lazy_property_names (bool separate_enumerable, +ecma_op_bound_function_list_lazy_property_names (uint32_t opts, ecma_collection_t *main_collection_p, ecma_collection_t *non_enum_collection_p); diff --git a/jerry-core/ecma/operations/ecma-objects.c b/jerry-core/ecma/operations/ecma-objects.c index ab12b51aa..2dc49b9c9 100644 --- a/jerry-core/ecma/operations/ecma-objects.c +++ b/jerry-core/ecma/operations/ecma-objects.c @@ -1862,7 +1862,8 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */ const bool is_array_indices_only = (opts & ECMA_LIST_ARRAY_INDICES) != 0; const bool is_with_prototype_chain = (opts & ECMA_LIST_PROTOTYPE) != 0; #if ENABLED (JERRY_ES2015) - const bool is_symbols_only = (opts & ECMA_LIST_SYMBOLS) != 0; + const bool is_symbols = (opts & ECMA_LIST_SYMBOLS) != 0; + const bool is_symbols_only = (opts & ECMA_LIST_SYMBOLS_ONLY) != 0; #endif /* ENABLED (JERRY_ES2015) */ const size_t bitmap_row_size = sizeof (uint32_t) * JERRY_BITSINBYTE; @@ -1877,7 +1878,9 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */ { ecma_length_t string_named_properties_count = 0; ecma_length_t array_index_named_properties_count = 0; - +#if ENABLED (JERRY_ES2015) + ecma_length_t symbol_named_properties_count = 0; +#endif /* ENABLED (JERRY_ES2015) */ ecma_collection_t *prop_names_p = ecma_new_collection (); #if ENABLED (JERRY_ES2015) @@ -1888,7 +1891,7 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */ if (obj_is_builtin) { ecma_builtin_list_lazy_property_names (obj_p, - is_enumerable_only, + opts, prop_names_p, skipped_non_enumerable_p); } @@ -1912,21 +1915,21 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */ #endif /* ENABLED (JERRY_ES2015) */ { ecma_op_function_list_lazy_property_names (obj_p, - is_enumerable_only, + opts, prop_names_p, skipped_non_enumerable_p); break; } case ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION: { - ecma_op_external_function_list_lazy_property_names (is_enumerable_only, + ecma_op_external_function_list_lazy_property_names (opts, prop_names_p, skipped_non_enumerable_p); break; } case ECMA_OBJECT_TYPE_BOUND_FUNCTION: { - ecma_op_bound_function_list_lazy_property_names (is_enumerable_only, + ecma_op_bound_function_list_lazy_property_names (opts, prop_names_p, skipped_non_enumerable_p); break; @@ -1938,7 +1941,7 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */ if (ext_object_p->u.class_prop.class_id == LIT_MAGIC_STRING_STRING_UL) { ecma_op_string_list_lazy_property_names (obj_p, - is_enumerable_only, + opts, prop_names_p, skipped_non_enumerable_p); } @@ -1948,7 +1951,7 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */ case ECMA_OBJECT_TYPE_ARRAY: { ecma_op_array_list_lazy_property_names (obj_p, - is_enumerable_only, + opts, prop_names_p, skipped_non_enumerable_p); break; @@ -1975,6 +1978,21 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */ { ecma_string_t *name_p = ecma_get_string_from_value (buffer_p[i]); + if (ecma_string_get_array_index (name_p) != ECMA_STRING_NOT_ARRAY_INDEX) + { + array_index_named_properties_count++; + } +#if ENABLED (JERRY_ES2015) + else if (ecma_prop_name_is_symbol (name_p)) + { + symbol_named_properties_count++; + } +#endif /* ENABLED (JERRY_ES2015) */ + else + { + string_named_properties_count++; + } + #if ENABLED (JERRY_ES2015) /* Symbols are never lazy listed */ JERRY_ASSERT (!ecma_prop_name_is_symbol (name_p)); @@ -1997,6 +2015,7 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */ ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) prototype_chain_iter_p; uint32_t length = ext_obj_p->u.array.length; + array_index_named_properties_count = length; ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, prop_iter_cp); @@ -2081,12 +2100,13 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */ if (!(is_enumerable_only && !ecma_is_property_enumerable (*property_p))) { #if ENABLED (JERRY_ES2015) - /* If is_symbols_only is false and prop_name is symbol - we should skip the current property e.g. for-in. - - Also if is_symbols_only is true and prop_name is not symbol - we should skip the current property e.g. Object.getOwnPropertySymbols. */ - if (JERRY_UNLIKELY (is_symbols_only != ecma_prop_name_is_symbol (name_p))) + /* We skip the current property in the following cases: + 1. We don't want to list symbols (is_symbols and is_symbols_only are false) + and the current property is a symbol. + 2. We only want to list symbols (is_symbols_only is true) and the current + property is NOT a symbol. */ + bool is_symbol = ecma_prop_name_is_symbol (name_p); + if ((!(is_symbols || is_symbols_only) && is_symbol) || (is_symbols_only && !is_symbol)) { ecma_deref_ecma_string (name_p); continue; @@ -2117,6 +2137,31 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */ if (is_add) { + if (ecma_string_get_array_index (name_p) != ECMA_STRING_NOT_ARRAY_INDEX) + { + /* The name is a valid array index. */ + array_index_named_properties_count++; + } + else if (!is_array_indices_only) + { + #if ENABLED (JERRY_ES2015) + if (ecma_prop_name_is_symbol (name_p)) + { + symbol_named_properties_count++; + } + else + { + #endif /* ENABLED (JERRY_ES2015) */ + string_named_properties_count++; + #if ENABLED (JERRY_ES2015) + } + #endif /* ENABLED (JERRY_ES2015) */ + } + else + { + continue; + } + own_names_hashes_bitmap[bitmap_row] |= (1u << bitmap_column); ecma_collection_push_back (prop_names_p, ecma_make_prop_name_value (name_p)); @@ -2139,39 +2184,32 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */ } } - buffer_p = prop_names_p->buffer_p; + ecma_length_t all_properties_count = array_index_named_properties_count + string_named_properties_count; - for (uint32_t i = 0; i < prop_names_p->item_count; i++) - { - ecma_string_t *name_p = ecma_get_prop_name_from_value (buffer_p[i]); +#if ENABLED (JERRY_ES2015) + all_properties_count += symbol_named_properties_count; +#endif /* ENABLED (JERRY_ES2015) */ - uint32_t index = ecma_string_get_array_index (name_p); + /* Second pass: collecting property names into an array. */ + JMEM_DEFINE_LOCAL_ARRAY (names_p, all_properties_count, ecma_string_t *); - if (index != ECMA_STRING_NOT_ARRAY_INDEX) - { - /* The name is a valid array index. */ - array_index_named_properties_count++; - } - else if (!is_array_indices_only) - { - string_named_properties_count++; - } - } + ecma_string_t **string_names_p = names_p + array_index_named_properties_count; +#if ENABLED (JERRY_ES2015) + ecma_string_t **symbol_names_p = string_names_p + string_named_properties_count; +#endif /* ENABLED (JERRY_ES2015) */ - /* Second pass: collecting property names into arrays. */ - JMEM_DEFINE_LOCAL_ARRAY (names_p, - array_index_named_properties_count + string_named_properties_count, - ecma_string_t *); - JMEM_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; + uint32_t string_name_pos = string_named_properties_count; +#if ENABLED (JERRY_ES2015) + uint32_t symbol_name_pos = symbol_named_properties_count; +#endif /* ENABLED (JERRY_ES2015) */ buffer_p = prop_names_p->buffer_p; for (uint32_t i = 0; i < prop_names_p->item_count; i++) { ecma_string_t *name_p = ecma_get_prop_name_from_value (buffer_p[i]); + ecma_ref_ecma_string (name_p); uint32_t index = ecma_string_get_array_index (name_p); @@ -2181,64 +2219,63 @@ 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 > ecma_string_get_array_index (names_p[insertion_pos])) { insertion_pos++; } if (insertion_pos == array_index_name_pos) { - array_index_names_p[array_index_name_pos++] = index; + names_p[array_index_name_pos++] = name_p; } else { JERRY_ASSERT (insertion_pos < array_index_name_pos); - JERRY_ASSERT (index >= array_index_names_p[insertion_pos]); + JERRY_ASSERT (index <= ecma_string_get_array_index (names_p[insertion_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]; + names_p[move_pos] = names_p[move_pos - 1u]; move_pos--; } - array_index_names_p[insertion_pos] = index; + names_p[insertion_pos] = name_p; } } - else if (!is_array_indices_only) +#if ENABLED (JERRY_ES2015) + else if (ecma_prop_name_is_symbol (name_p)) { - /* - * Filling from end to begin, as list of object's properties is sorted - * in order that is reverse to properties creation order - */ + // Put in the symbols in reverse order. + JERRY_ASSERT (symbol_name_pos > 0); + JERRY_ASSERT (symbol_name_pos <= symbol_named_properties_count); - JERRY_ASSERT (name_pos > 0 - && name_pos <= array_index_named_properties_count + string_named_properties_count); - ecma_ref_ecma_string (name_p); - names_p[--name_pos] = name_p; + symbol_names_p[--symbol_name_pos] = name_p; + } +#endif /* ENABLED (JERRY_ES2015) */ + else + { + // Put in the strings in reverse order. + JERRY_ASSERT (string_name_pos > 0); + JERRY_ASSERT (string_name_pos <= string_named_properties_count); + + string_names_p[--string_name_pos] = name_p; } } - 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); - - JMEM_FINALIZE_LOCAL_ARRAY (array_index_names_p); + JERRY_ASSERT (array_index_name_pos == array_index_named_properties_count); + JERRY_ASSERT (string_name_pos == 0); +#if ENABLED (JERRY_ES2015) + JERRY_ASSERT (symbol_name_pos == 0); +#endif /* ENABLED (JERRY_ES2015) */ ecma_collection_free (prop_names_p); /* Third pass: * embedding own property names of current object of prototype chain to aggregate property names collection */ - for (uint32_t i = 0; - i < array_index_named_properties_count + string_named_properties_count; - i++) + for (uint32_t i = 0; i < all_properties_count; i++) { bool is_append = true; diff --git a/jerry-core/ecma/operations/ecma-string-object.c b/jerry-core/ecma/operations/ecma-string-object.c index 271225bef..4b752ff47 100644 --- a/jerry-core/ecma/operations/ecma-string-object.c +++ b/jerry-core/ecma/operations/ecma-string-object.c @@ -84,13 +84,8 @@ ecma_op_create_string_object (const ecma_value_t *arguments_list_p, /**< list of */ void ecma_op_string_list_lazy_property_names (ecma_object_t *obj_p, /**< a String object */ - bool separate_enumerable, /**< true - list enumerable properties - * into main collection, - * and non-enumerable to collection of - * 'skipped non-enumerable' properties, - * false - list all properties into main - * collection. - */ + uint32_t opts, /**< listing options using flags + * from ecma_list_properties_options_t */ ecma_collection_t *main_collection_p, /**< 'main' collection */ ecma_collection_t *non_enum_collection_p) /**< skipped * 'non-enumerable' @@ -100,7 +95,7 @@ ecma_op_string_list_lazy_property_names (ecma_object_t *obj_p, /**< a String obj ecma_collection_t *for_enumerable_p = main_collection_p; - ecma_collection_t *for_non_enumerable_p = separate_enumerable ? non_enum_collection_p : main_collection_p; + ecma_collection_t *for_non_enumerable_p = (opts & ECMA_LIST_ENUMERABLE) ? non_enum_collection_p : main_collection_p; ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; JERRY_ASSERT (ext_object_p->u.class_prop.class_id == LIT_MAGIC_STRING_STRING_UL); @@ -117,7 +112,10 @@ ecma_op_string_list_lazy_property_names (ecma_object_t *obj_p, /**< a String obj ecma_collection_push_back (for_enumerable_p, ecma_make_string_value (name_p)); } - ecma_collection_push_back (for_non_enumerable_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); + if ((opts & ECMA_LIST_ARRAY_INDICES) == 0) + { + ecma_collection_push_back (for_non_enumerable_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); + } } /* ecma_op_string_list_lazy_property_names */ /** diff --git a/jerry-core/ecma/operations/ecma-string-object.h b/jerry-core/ecma/operations/ecma-string-object.h index b1c4b7ad9..640524106 100644 --- a/jerry-core/ecma/operations/ecma-string-object.h +++ b/jerry-core/ecma/operations/ecma-string-object.h @@ -30,7 +30,7 @@ ecma_op_create_string_object (const ecma_value_t *arguments_list_p, ecma_length_ void ecma_op_string_list_lazy_property_names (ecma_object_t *obj_p, - bool separate_enumerable, + uint32_t opts, ecma_collection_t *main_collection_p, ecma_collection_t *non_enum_collection_p); diff --git a/tests/jerry/es2015/object-assign.js b/tests/jerry/es2015/object-assign.js index f4fc0055c..93ed999d1 100644 --- a/tests/jerry/es2015/object-assign.js +++ b/tests/jerry/es2015/object-assign.js @@ -156,3 +156,12 @@ try { } catch (e) { assert (e instanceof TypeError) } + +var asd = Symbol ("asd"); +var foo = Symbol ("foo"); +var bar = Symbol ("bar"); +var obj = {1: 5, "a": 6, [foo]: 7, [asd]: 8, [bar]: 9}; +var result = Object.assign ({}, obj); +assert (result[foo] == 7); +assert (result[asd] == 8); +assert (result[bar] == 9); diff --git a/tests/jerry/es2015/object-get-own-property-names.js b/tests/jerry/es2015/object-get-own-property-names.js new file mode 100644 index 000000000..6bc795051 --- /dev/null +++ b/tests/jerry/es2015/object-get-own-property-names.js @@ -0,0 +1,23 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Check that Object.getOwnPropertyNames does NOT include Symbols by default. +var asd = Symbol ("asd"); +var foo = Symbol ("foo"); +var bar = Symbol ("bar"); +var result = Object.getOwnPropertyNames ({1: 5, "a": 6, [foo]: 7, [asd]: 8, [bar]: 9}); +assert (!Object.hasOwnProperty (result, foo)); +assert (!Object.hasOwnProperty (result, asd)); +assert (!Object.hasOwnProperty (result, bar));