diff --git a/jerry-core/api/jerry.c b/jerry-core/api/jerry.c index e53c587dc4..51078c9f6a 100644 --- a/jerry-core/api/jerry.c +++ b/jerry-core/api/jerry.c @@ -4604,10 +4604,16 @@ jerry_object_get_property_names (const jerry_value_t obj_val, /**< object */ ecma_ref_object (obj_iter_p); + if ((filter & JERRY_PROPERTY_FILTER_EXLCUDE_STRINGS) + && !(filter & JERRY_PROPERTY_FILTER_INTEGER_INDICES_AS_NUMBER)) + { + filter |= JERRY_PROPERTY_FILTER_EXLCUDE_INTEGER_INDICES; + } + while (true) { /* Step 1. Get Object.[[OwnKeys]] */ - ecma_collection_t *prop_names_p = ecma_op_object_own_property_keys (obj_iter_p); + ecma_collection_t *prop_names_p = ecma_op_object_own_property_keys (obj_iter_p, filter); #if JERRY_BUILTIN_PROXY if (prop_names_p == NULL) @@ -4623,34 +4629,7 @@ jerry_object_get_property_names (const jerry_value_t obj_val, /**< object */ ecma_string_t *key_p = ecma_get_prop_name_from_value (key); uint32_t index = ecma_string_get_array_index (key_p); - /* Step 2. Filter by key type */ - if (filter & (JERRY_PROPERTY_FILTER_EXLCUDE_STRINGS - | JERRY_PROPERTY_FILTER_EXLCUDE_SYMBOLS - | JERRY_PROPERTY_FILTER_EXLCUDE_INTEGER_INDICES)) - { - if (ecma_is_value_symbol (key)) - { - if (filter & JERRY_PROPERTY_FILTER_EXLCUDE_SYMBOLS) - { - continue; - } - } - else if (index != ECMA_STRING_NOT_ARRAY_INDEX) - { - if ((filter & JERRY_PROPERTY_FILTER_EXLCUDE_INTEGER_INDICES) - || ((filter & JERRY_PROPERTY_FILTER_EXLCUDE_STRINGS) - && !(filter & JERRY_PROPERTY_FILTER_INTEGER_INDICES_AS_NUMBER))) - { - continue; - } - } - else if (filter & JERRY_PROPERTY_FILTER_EXLCUDE_STRINGS) - { - continue; - } - } - - /* Step 3. Filter property attributes */ + /* Step 2. Filter property attributes */ if (filter & (JERRY_PROPERTY_FILTER_EXLCUDE_NON_CONFIGURABLE | JERRY_PROPERTY_FILTER_EXLCUDE_NON_ENUMERABLE | JERRY_PROPERTY_FILTER_EXLCUDE_NON_WRITABLE)) @@ -4729,7 +4708,7 @@ jerry_object_get_property_names (const jerry_value_t obj_val, /**< object */ ecma_collection_free (prop_names_p); - /* Step 4: Traverse prototype chain */ + /* Step 3: Traverse prototype chain */ if ((filter & JERRY_PROPERTY_FILTER_TRAVERSE_PROTOTYPE_CHAIN) != JERRY_PROPERTY_FILTER_TRAVERSE_PROTOTYPE_CHAIN) { diff --git a/jerry-core/ecma/base/ecma-globals.h b/jerry-core/ecma/base/ecma-globals.h index 6a9918f4b0..844a354a95 100644 --- a/jerry-core/ecma/base/ecma-globals.h +++ b/jerry-core/ecma/base/ecma-globals.h @@ -223,13 +223,14 @@ enum ECMA_VALUE_SPREAD_ELEMENT = ECMA_MAKE_VALUE (11), /**< a special value for spread elements in array initialization * or function call argument list */ /* Other values */ - ECMA_VALUE_INITIALIZED = ECMA_MAKE_VALUE (12), /**< represents initialized mapped arguments formal parameter */ + ECMA_VALUE_ARGUMENT_INITIALIZED = ECMA_MAKE_VALUE (12), /**< represents initialized mapped arguments formal parameter */ + ECMA_VALUE_ARGUMENT_NO_TRACK = ECMA_MAKE_VALUE (13), /**< represents initialized mapped arguments formal parameter */ #if JERRY_ESNEXT - ECMA_VALUE_SYNC_ITERATOR = ECMA_MAKE_VALUE (13), /**< option for ecma_op_get_iterator: sync iterator is requested */ - ECMA_VALUE_ASYNC_ITERATOR = ECMA_MAKE_VALUE (14), /**< option for ecma_op_get_iterator: async iterator is requested */ + ECMA_VALUE_SYNC_ITERATOR = ECMA_MAKE_VALUE (14), /**< option for ecma_op_get_iterator: sync iterator is requested */ + ECMA_VALUE_ASYNC_ITERATOR = ECMA_MAKE_VALUE (15), /**< option for ecma_op_get_iterator: async iterator is requested */ #endif /* JERRY_ESNEXT */ #if JERRY_BUILTIN_GLOBAL_THIS - ECMA_VALUE_GLOBAL_THIS = ECMA_MAKE_VALUE (15), /**< globalThis built-in */ + ECMA_VALUE_GLOBAL_THIS = ECMA_MAKE_VALUE (16), /**< globalThis built-in */ #endif /* JERRY_BUILTIN_GLOBAL_THIS */ }; @@ -2439,8 +2440,6 @@ typedef struct uint32_t array_index_named_props; /**< number of array index named properties */ uint32_t string_named_props; /**< number of string named properties */ uint32_t symbol_named_props; /**< number of symbol named properties */ - uint32_t lazy_string_named_props; /**< number of lazy instantiated string properties */ - uint32_t lazy_symbol_named_props; /**< number of lazy instantiated symbol properties */ } ecma_property_counter_t; /** @@ -2452,9 +2451,8 @@ typedef enum ECMA_ARGUMENTS_OBJECT_MAPPED = (1 << 0), /* mapped arguments object */ ECMA_ARGUMENTS_OBJECT_STATIC_BYTECODE = (1 << 1), /* static mapped arguments object */ ECMA_ARGUMENTS_OBJECT_CALLEE_INITIALIZED = (1 << 2), /* 'callee' property has been lazy initialized */ - ECMA_ARGUMENTS_OBJECT_CALLER_INITIALIZED = (1 << 3), /* 'caller' property has been lazy initialized */ - ECMA_ARGUMENTS_OBJECT_LENGTH_INITIALIZED = (1 << 4), /* 'length' property has been lazy initialized */ - ECMA_ARGUMENTS_OBJECT_ITERATOR_INITIALIZED = (1 << 5), /* 'Symbol.iterator' property has been lazy initialized */ + ECMA_ARGUMENTS_OBJECT_LENGTH_INITIALIZED = (1 << 3), /* 'length' property has been lazy initialized */ + ECMA_ARGUMENTS_OBJECT_ITERATOR_INITIALIZED = (1 << 4), /* 'Symbol.iterator' property has been lazy initialized */ } ecma_arguments_object_flags_t; /** diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-object.c b/jerry-core/ecma/builtin-objects/ecma-builtin-object.c index 52275fe24c..031a19dce9 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-object.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-object.c @@ -336,7 +336,7 @@ ecma_builtin_object_set_integrity_level (ecma_object_t *obj_p, /**< object */ } /* 6. */ - ecma_collection_t *props_p = ecma_op_object_own_property_keys (obj_p); + ecma_collection_t *props_p = ecma_op_object_own_property_keys (obj_p, JERRY_PROPERTY_FILTER_ALL); #if JERRY_BUILTIN_PROXY if (props_p == NULL) @@ -596,7 +596,7 @@ ecma_builtin_object_test_integrity_level (ecma_object_t *obj_p, /**< routine's a ecma_value_t ret_value = ECMA_VALUE_TRUE; /* 2. */ - ecma_collection_t *props_p = ecma_op_object_own_property_keys (obj_p); + ecma_collection_t *props_p = ecma_op_object_own_property_keys (obj_p, JERRY_PROPERTY_FILTER_ALL); #if JERRY_BUILTIN_PROXY if (props_p == NULL) @@ -750,7 +750,7 @@ static ecma_value_t ecma_builtin_object_object_get_own_property_descriptors (ecma_object_t *obj_p) /**< routine's first argument */ { /* 2 */ - ecma_collection_t *prop_names_p = ecma_op_object_own_property_keys (obj_p); + ecma_collection_t *prop_names_p = ecma_op_object_own_property_keys (obj_p, JERRY_PROPERTY_FILTER_ALL); #if JERRY_BUILTIN_PROXY if (prop_names_p == NULL) @@ -831,7 +831,7 @@ ecma_builtin_object_object_define_properties (ecma_object_t *obj_p, /**< routine ecma_object_t *props_p = ecma_get_object_from_value (props); /* 3. */ - ecma_collection_t *prop_names_p = ecma_op_object_own_property_keys (props_p); + ecma_collection_t *prop_names_p = ecma_op_object_own_property_keys (props_p, JERRY_PROPERTY_FILTER_ALL); ecma_value_t ret_value = ECMA_VALUE_ERROR; #if JERRY_BUILTIN_PROXY @@ -1073,7 +1073,7 @@ 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 */ - ecma_collection_t *props_p = ecma_op_object_own_property_keys (from_obj_p); + ecma_collection_t *props_p = ecma_op_object_own_property_keys (from_obj_p, JERRY_PROPERTY_FILTER_ALL); #if JERRY_BUILTIN_PROXY if (props_p == NULL) @@ -1327,41 +1327,27 @@ ecma_op_object_get_own_property_keys (ecma_value_t this_arg, /**< this argument ecma_object_t *obj_p = ecma_get_object_from_value (object); /* 2. */ - ecma_collection_t *props_p = ecma_op_object_own_property_keys (obj_p); + jerry_property_filter_t filter = JERRY_PROPERTY_FILTER_EXLCUDE_SYMBOLS; - if (props_p == NULL) + if (type == ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_SYMBOLS) { - ecma_deref_object (obj_p); - return ECMA_VALUE_ERROR; + filter = (JERRY_PROPERTY_FILTER_EXLCUDE_STRINGS + | JERRY_PROPERTY_FILTER_EXLCUDE_INTEGER_INDICES); } - /* 3. */ - ecma_collection_t *name_list_p = ecma_new_collection (); + ecma_collection_t *props_p = ecma_op_object_own_property_keys (obj_p, filter); + ecma_deref_object (obj_p); - /* 4. */ - for (uint32_t i = 0; i < props_p->item_count; i++) + if (props_p == NULL) { - ecma_value_t prop_name = props_p->buffer_p[i]; - ecma_string_t *name_p = ecma_get_prop_name_from_value (prop_name); - - if ((ecma_prop_name_is_symbol (name_p) && type == ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_SYMBOLS) - || (ecma_is_value_string (prop_name) && type == ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_NAMES)) - { - ecma_ref_ecma_string (name_p); - ecma_collection_push_back (name_list_p, prop_name); - } + return ECMA_VALUE_ERROR; } - ecma_value_t result_array = ecma_op_new_array_object_from_collection (name_list_p, false); - - ecma_deref_object (obj_p); - ecma_collection_free (props_p); - - return result_array; + return ecma_op_new_array_object_from_collection (props_p, false); #else /* !JERRY_ESNEXT */ JERRY_UNUSED (type); ecma_object_t *obj_p = ecma_get_object_from_value (this_arg); - ecma_collection_t *props_p = ecma_op_object_own_property_keys (obj_p); + ecma_collection_t *props_p = ecma_op_object_own_property_keys (obj_p, JERRY_PROPERTY_FILTER_ALL); return ecma_op_new_array_object_from_collection (props_p, false); #endif /* JERRY_ESNEXT */ } /* ecma_op_object_get_own_property_keys */ diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-reflect.c b/jerry-core/ecma/builtin-objects/ecma-builtin-reflect.c index 5e7485bfe3..484dfa0639 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-reflect.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-reflect.c @@ -163,7 +163,7 @@ ecma_builtin_reflect_dispatch_routine (uint8_t builtin_routine_id, /**< built-in ecma_object_t *target_p = ecma_get_object_from_value (arguments_list[0]); /* 2. */ - ecma_collection_t *prop_names = ecma_op_object_own_property_keys (target_p); + ecma_collection_t *prop_names = ecma_op_object_own_property_keys (target_p, JERRY_PROPERTY_FILTER_ALL); #if JERRY_BUILTIN_PROXY if (prop_names == NULL) @@ -206,7 +206,7 @@ ecma_builtin_reflect_dispatch_routine (uint8_t builtin_routine_id, /**< built-in return ecma_raise_type_error (ECMA_ERR_MSG ("Reflect.construct expects an object as second argument")); } - ecma_collection_t *coll_p = ecma_op_create_list_from_array_like (arguments_list[1], false); + ecma_collection_t *coll_p = ecma_op_create_list_from_array_like (arguments_list[1], ECMA_FROM_ARRAY_LIKE_ANY); if (coll_p == NULL) { diff --git a/jerry-core/ecma/builtin-objects/ecma-builtins.c b/jerry-core/ecma/builtin-objects/ecma-builtins.c index dc621e2b19..0a610cac47 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtins.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtins.c @@ -1414,11 +1414,17 @@ ecma_builtin_native_handler_list_lazy_property_names (ecma_object_t *object_p, / void ecma_builtin_routine_list_lazy_property_names (ecma_object_t *object_p, /**< a built-in object */ ecma_collection_t *prop_names_p, /**< prop name collection */ - ecma_property_counter_t *prop_counter_p) /**< prop counter */ + ecma_property_counter_t *prop_counter_p, /**< property counters */ + jerry_property_filter_t filter) /**< name filters */ { JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION); JERRY_ASSERT (ecma_builtin_function_is_routine (object_p)); + if (filter & JERRY_PROPERTY_FILTER_EXLCUDE_STRINGS) + { + return; + } + #if JERRY_ESNEXT ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p; @@ -1456,7 +1462,8 @@ ecma_builtin_routine_list_lazy_property_names (ecma_object_t *object_p, /**< a b void ecma_builtin_list_lazy_property_names (ecma_object_t *object_p, /**< a built-in object */ ecma_collection_t *prop_names_p, /**< prop name collection */ - ecma_property_counter_t *prop_counter_p) /**< prop counter */ + ecma_property_counter_t *prop_counter_p, /**< property counters */ + jerry_property_filter_t filter) /**< name filters */ { JERRY_ASSERT (ecma_get_object_type (object_p) != ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION || !ecma_builtin_function_is_routine (object_p)); @@ -1477,57 +1484,95 @@ ecma_builtin_list_lazy_property_names (ecma_object_t *object_p, /**< a built-in JERRY_ASSERT (builtin_id < ECMA_BUILTIN_ID__COUNT); - const ecma_builtin_property_descriptor_t *curr_property_p = ecma_builtin_property_list_references[builtin_id]; - - uint32_t index = 0; - uint8_t bitset = built_in_props_p->u2.instantiated_bitset[0]; +#if JERRY_ESNEXT + bool has_symbol = true; +#endif /* JERRY_BUILTIN_REALMS */ + if (!(filter & JERRY_PROPERTY_FILTER_EXLCUDE_STRINGS)) + { + const ecma_builtin_property_descriptor_t *curr_property_p = ecma_builtin_property_list_references[builtin_id]; + uint8_t bitset = built_in_props_p->u2.instantiated_bitset[0]; #if JERRY_BUILTIN_REALMS - uint8_t *bitset_p = built_in_props_p->u2.instantiated_bitset + 1 + sizeof (ecma_value_t); + uint8_t *bitset_p = built_in_props_p->u2.instantiated_bitset + 1 + sizeof (ecma_value_t); #else /* !JERRY_BUILTIN_REALMS */ - uint8_t *bitset_p = built_in_props_p->u2.instantiated_bitset + 1; + uint8_t *bitset_p = built_in_props_p->u2.instantiated_bitset + 1; #endif /* JERRY_BUILTIN_REALMS */ + uint32_t index = 0; - while (curr_property_p->magic_string_id != LIT_MAGIC_STRING__COUNT) - { - if (index == 8) +#if JERRY_ESNEXT + has_symbol = false; +#endif /* JERRY_BUILTIN_REALMS */ + + while (curr_property_p->magic_string_id != LIT_MAGIC_STRING__COUNT) { - bitset = *bitset_p++; - index = 0; - } + if (index == 8) + { + bitset = *bitset_p++; + index = 0; + } - uint32_t bit_for_index = (uint32_t) 1u << index; + uint32_t bit_for_index = (uint32_t) 1u << index; - if (curr_property_p->magic_string_id > LIT_NON_INTERNAL_MAGIC_STRING__COUNT) - { #if JERRY_ESNEXT - if (LIT_IS_GLOBAL_SYMBOL (curr_property_p->magic_string_id)) - { - ecma_string_t *name_p = ecma_op_get_global_symbol (curr_property_p->magic_string_id); + bool is_symbol = (curr_property_p->magic_string_id > LIT_NON_INTERNAL_MAGIC_STRING__COUNT); +#else /* !JERRY_ESNEXT */ + bool is_symbol = false; +#endif /* JERRY_ESNEXT */ - if (!(bitset & bit_for_index)) - { - ecma_value_t name = ecma_make_symbol_value (name_p); - ecma_collection_push_back (prop_names_p, name); - prop_counter_p->symbol_named_props++; - } - else - { - ecma_deref_ecma_string (name_p); - } - } + if (is_symbol) + { +#if JERRY_ESNEXT + JERRY_ASSERT (LIT_IS_GLOBAL_SYMBOL (curr_property_p->magic_string_id)); + has_symbol = true; #endif /* JERRY_ESNEXT */ + } + else if (!(bitset & bit_for_index)) + { + ecma_value_t name = ecma_make_magic_string_value ((lit_magic_string_id_t) curr_property_p->magic_string_id); + ecma_collection_push_back (prop_names_p, name); + prop_counter_p->string_named_props++; + } + + curr_property_p++; + index++; } - else if (!(bitset & bit_for_index)) + } + +#if JERRY_ESNEXT + if (!(filter & JERRY_PROPERTY_FILTER_EXLCUDE_SYMBOLS) && has_symbol) + { + const ecma_builtin_property_descriptor_t *curr_property_p = ecma_builtin_property_list_references[builtin_id]; + uint8_t bitset = built_in_props_p->u2.instantiated_bitset[0]; +#if JERRY_BUILTIN_REALMS + uint8_t *bitset_p = built_in_props_p->u2.instantiated_bitset + 1 + sizeof (ecma_value_t); +#else /* !JERRY_BUILTIN_REALMS */ + uint8_t *bitset_p = built_in_props_p->u2.instantiated_bitset + 1; +#endif /* JERRY_BUILTIN_REALMS */ + uint32_t index = 0; + + while (curr_property_p->magic_string_id != LIT_MAGIC_STRING__COUNT) { - ecma_value_t name = ecma_make_magic_string_value ((lit_magic_string_id_t) curr_property_p->magic_string_id); - ecma_collection_push_back (prop_names_p, name); - prop_counter_p->string_named_props++; - } + if (index == 8) + { + bitset = *bitset_p++; + index = 0; + } - curr_property_p++; - index++; + uint32_t bit_for_index = (uint32_t) 1u << index; + + if (curr_property_p->magic_string_id > LIT_NON_INTERNAL_MAGIC_STRING__COUNT + && !(bitset & bit_for_index)) + { + ecma_string_t *name_p = ecma_op_get_global_symbol (curr_property_p->magic_string_id); + ecma_collection_push_back (prop_names_p, ecma_make_symbol_value (name_p)); + prop_counter_p->symbol_named_props++; + } + + curr_property_p++; + index++; + } } +#endif /* JERRY_ESNEXT */ } /* ecma_builtin_list_lazy_property_names */ /** diff --git a/jerry-core/ecma/builtin-objects/ecma-builtins.h b/jerry-core/ecma/builtin-objects/ecma-builtins.h index 2a50e5df08..22578fa1c7 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtins.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtins.h @@ -138,13 +138,13 @@ ecma_builtin_routine_delete_built_in_property (ecma_object_t *object_p, ecma_str void ecma_builtin_delete_built_in_property (ecma_object_t *object_p, ecma_string_t *property_name_p); void -ecma_builtin_routine_list_lazy_property_names (ecma_object_t *object_p, - ecma_collection_t *prop_names_p, - ecma_property_counter_t *prop_counter_p); +ecma_builtin_routine_list_lazy_property_names (ecma_object_t *object_p, ecma_collection_t *prop_names_p, + ecma_property_counter_t *prop_counter_p, + jerry_property_filter_t filter); void -ecma_builtin_list_lazy_property_names (ecma_object_t *object_p, - ecma_collection_t *prop_names_p, - ecma_property_counter_t *prop_counter_p); +ecma_builtin_list_lazy_property_names (ecma_object_t *object_p, ecma_collection_t *prop_names_p, + ecma_property_counter_t *prop_counter_p, + jerry_property_filter_t filter); bool ecma_builtin_is_global (ecma_object_t *object_p); ecma_object_t * diff --git a/jerry-core/ecma/operations/ecma-arguments-object.c b/jerry-core/ecma/operations/ecma-arguments-object.c index 9ae1cf2dd0..2aa53ddc5c 100644 --- a/jerry-core/ecma/operations/ecma-arguments-object.c +++ b/jerry-core/ecma/operations/ecma-arguments-object.c @@ -88,7 +88,7 @@ ecma_op_create_arguments_object (vm_frame_ctx_shared_args_t *shared_p, /**< shar for (uint32_t i = shared_p->arg_list_len; i < saved_arg_count; i++) { - argv_p[i] = ECMA_VALUE_INITIALIZED; + argv_p[i] = ECMA_VALUE_ARGUMENT_INITIALIZED; } arguments_p->header.u.cls.u3.arguments_number = shared_p->arg_list_len; @@ -137,7 +137,7 @@ ecma_op_create_arguments_object (vm_frame_ctx_shared_args_t *shared_p, /**< shar ecma_deref_ecma_string (prop_name_p); - prop_value_p->value = argv_p[i] == ECMA_VALUE_INITIALIZED ? ECMA_VALUE_UNDEFINED : argv_p[i]; + prop_value_p->value = (argv_p[i] == ECMA_VALUE_ARGUMENT_INITIALIZED) ? ECMA_VALUE_UNDEFINED : argv_p[i]; argv_p[i] = ECMA_VALUE_EMPTY; } } @@ -188,7 +188,7 @@ ecma_op_arguments_object_define_own_property (ecma_object_t *object_p, /**< the if (property_desc_p->flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED)) { ecma_free_value_if_not_object (argv_p[index]); - argv_p[index] = ECMA_VALUE_EMPTY; + argv_p[index] = ECMA_VALUE_ARGUMENT_NO_TRACK; } else { @@ -209,7 +209,7 @@ ecma_op_arguments_object_define_own_property (ecma_object_t *object_p, /**< the && !(property_desc_p->flags & JERRY_PROP_IS_WRITABLE)) { ecma_free_value_if_not_object (argv_p[index]); - argv_p[index] = ECMA_VALUE_EMPTY; + argv_p[index] = ECMA_VALUE_ARGUMENT_NO_TRACK; } } } @@ -217,43 +217,6 @@ ecma_op_arguments_object_define_own_property (ecma_object_t *object_p, /**< the return ret_value; } /* ecma_op_arguments_object_define_own_property */ -/** - * [[Delete]] ecma Arguments object's operation - * - * See also: - * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 - * ECMA-262 v5, 10.6 - * - * @return ecma value - * Returned value must be freed with ecma_free_value - */ -ecma_value_t -ecma_op_arguments_object_delete (ecma_object_t *object_p, /**< the object */ - ecma_string_t *property_name_p, /**< property name */ - bool is_throw) /**< flag that controls failure handling */ -{ - /* 3. */ - ecma_value_t ret_value = ecma_op_general_object_delete (object_p, property_name_p, is_throw); - - if (!ecma_is_value_true (ret_value) - || !(((ecma_extended_object_t *) object_p)->u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED)) - { - return ret_value; - } - - ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) object_p; - ecma_value_t *argv_p = (ecma_value_t *) (mapped_arguments_p + 1); - uint32_t index = ecma_string_get_array_index (property_name_p); - - if (index < mapped_arguments_p->unmapped.header.u.cls.u2.formal_params_number) - { - ecma_free_value_if_not_object (argv_p[index]); - argv_p[index] = ECMA_VALUE_EMPTY; - } - - return ret_value; -} /* ecma_op_arguments_object_delete */ - /** * Try to lazy instantiate the given property of a mapped/unmapped arguments object * @@ -269,7 +232,7 @@ ecma_op_arguments_object_try_to_lazy_instantiate_property (ecma_object_t *object ecma_unmapped_arguments_t *arguments_p = (ecma_unmapped_arguments_t *) object_p; ecma_value_t *argv_p = (ecma_value_t *) (arguments_p + 1); ecma_property_value_t *prop_value_p; - ecma_property_t *prop_p = NULL; + ecma_property_t *prop_p; uint32_t arguments_number = arguments_p->header.u.cls.u3.arguments_number; uint8_t flags = arguments_p->header.u.cls.u1.arguments_flags; @@ -283,57 +246,46 @@ ecma_op_arguments_object_try_to_lazy_instantiate_property (ecma_object_t *object if (index != ECMA_STRING_NOT_ARRAY_INDEX) { if (index >= arguments_number - || ecma_is_value_empty (argv_p[index]) - || argv_p[index] == ECMA_VALUE_INITIALIZED) + || ecma_is_value_empty (argv_p[index])) { return NULL; } + JERRY_ASSERT (argv_p[index] != ECMA_VALUE_ARGUMENT_INITIALIZED + && argv_p[index] != ECMA_VALUE_ARGUMENT_NO_TRACK); + prop_value_p = ecma_create_named_data_property (object_p, property_name_p, - ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, + ECMA_PROPERTY_BUILT_IN_CONFIGURABLE_ENUMERABLE_WRITABLE, &prop_p); /* Passing the reference */ prop_value_p->value = argv_p[index]; - /* Pevent reinitialization */ - if ((flags & ECMA_ARGUMENTS_OBJECT_MAPPED) - && index < arguments_p->header.u.cls.u2.formal_params_number) - { - argv_p[index] = ECMA_VALUE_INITIALIZED; - } - else - { - argv_p[index] = ECMA_VALUE_EMPTY; - } - + argv_p[index] = ECMA_VALUE_ARGUMENT_INITIALIZED; return prop_p; } - if (property_name_p == ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH) + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_LENGTH) && !(flags & ECMA_ARGUMENTS_OBJECT_LENGTH_INITIALIZED)) { - arguments_p->header.u.cls.u1.arguments_flags |= ECMA_ARGUMENTS_OBJECT_LENGTH_INITIALIZED; - prop_value_p = ecma_create_named_data_property (object_p, ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH), - ECMA_PROPERTY_CONFIGURABLE_WRITABLE, + ECMA_PROPERTY_BUILT_IN_CONFIGURABLE_WRITABLE, &prop_p); prop_value_p->value = ecma_make_uint32_value (arguments_number); + return prop_p; } - if (property_name_p == ecma_get_magic_string (LIT_MAGIC_STRING_CALLEE) + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_CALLEE) && !(flags & ECMA_ARGUMENTS_OBJECT_CALLEE_INITIALIZED)) { - arguments_p->header.u.cls.u1.arguments_flags |= ECMA_ARGUMENTS_OBJECT_CALLEE_INITIALIZED; - if (flags & ECMA_ARGUMENTS_OBJECT_MAPPED) { prop_value_p = ecma_create_named_data_property (object_p, property_name_p, - ECMA_PROPERTY_CONFIGURABLE_WRITABLE, + ECMA_PROPERTY_BUILT_IN_CONFIGURABLE_WRITABLE, &prop_p); prop_value_p->value = arguments_p->callee; @@ -346,44 +298,37 @@ ecma_op_arguments_object_try_to_lazy_instantiate_property (ecma_object_t *object ecma_get_magic_string (LIT_MAGIC_STRING_CALLEE), thrower_p, thrower_p, - ECMA_PROPERTY_FIXED, + ECMA_PROPERTY_BUILT_IN_FIXED, &prop_p); } return prop_p; } #if !JERRY_ESNEXT - if (property_name_p == ecma_get_magic_string (LIT_MAGIC_STRING_CALLER) - && !(arguments_p->header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_CALLER_INITIALIZED)) + if (property_name_p == ecma_get_magic_string (LIT_MAGIC_STRING_CALLER)) { if (arguments_p->header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED) { return NULL; } - arguments_p->header.u.cls.u1.arguments_flags |= ECMA_ARGUMENTS_OBJECT_CALLER_INITIALIZED; - ecma_object_t *thrower_p = ecma_builtin_get (ECMA_BUILTIN_ID_TYPE_ERROR_THROWER); ecma_create_named_accessor_property (object_p, ecma_get_magic_string (LIT_MAGIC_STRING_CALLER), thrower_p, thrower_p, - ECMA_PROPERTY_FIXED, + ECMA_PROPERTY_BUILT_IN_FIXED, &prop_p); return prop_p; } #else /* JERRY_ESNEXT */ - ecma_string_t *symbol_p = ecma_op_get_global_symbol (LIT_GLOBAL_SYMBOL_ITERATOR); - - if (property_name_p == symbol_p + if (ecma_op_compare_string_to_global_symbol (property_name_p, LIT_GLOBAL_SYMBOL_ITERATOR) && !(flags & ECMA_ARGUMENTS_OBJECT_ITERATOR_INITIALIZED)) { - arguments_p->header.u.cls.u1.arguments_flags |= ECMA_ARGUMENTS_OBJECT_ITERATOR_INITIALIZED; - prop_value_p = ecma_create_named_data_property (object_p, - symbol_p, - ECMA_PROPERTY_CONFIGURABLE_WRITABLE, + property_name_p, + ECMA_PROPERTY_BUILT_IN_CONFIGURABLE_WRITABLE, &prop_p); prop_value_p->value = ecma_op_object_get_by_magic_id (ecma_builtin_get (ECMA_BUILTIN_ID_INTRINSIC_OBJECT), @@ -391,71 +336,133 @@ ecma_op_arguments_object_try_to_lazy_instantiate_property (ecma_object_t *object JERRY_ASSERT (ecma_is_value_object (prop_value_p->value)); ecma_deref_object (ecma_get_object_from_value (prop_value_p->value)); + return prop_p; } - - ecma_deref_ecma_string (symbol_p); #endif /* !JERRY_ESNEXT */ - return prop_p; + return NULL; } /* ecma_op_arguments_object_try_to_lazy_instantiate_property */ +/** + * Delete configurable properties of arguments object + */ +void +ecma_op_arguments_delete_built_in_property (ecma_object_t *object_p, /**< the object */ + ecma_string_t *property_name_p) /**< property name */ +{ + ecma_unmapped_arguments_t *arguments_p = (ecma_unmapped_arguments_t *) object_p; + + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_LENGTH)) + { + JERRY_ASSERT (!(arguments_p->header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_LENGTH_INITIALIZED)); + + arguments_p->header.u.cls.u1.arguments_flags |= ECMA_ARGUMENTS_OBJECT_LENGTH_INITIALIZED; + return; + } + + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_CALLEE)) + { + JERRY_ASSERT (!(arguments_p->header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_CALLEE_INITIALIZED)); + JERRY_ASSERT (arguments_p->header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED); + + arguments_p->header.u.cls.u1.arguments_flags |= ECMA_ARGUMENTS_OBJECT_CALLEE_INITIALIZED; + return; + } + +#if JERRY_ESNEXT + if (ecma_prop_name_is_symbol (property_name_p)) + { + JERRY_ASSERT (!(arguments_p->header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_ITERATOR_INITIALIZED)); + JERRY_ASSERT (ecma_op_compare_string_to_global_symbol (property_name_p, LIT_GLOBAL_SYMBOL_ITERATOR)); + + arguments_p->header.u.cls.u1.arguments_flags |= ECMA_ARGUMENTS_OBJECT_ITERATOR_INITIALIZED; + return; + } +#endif /* JERRY_ESNEXT */ + + uint32_t index = ecma_string_get_array_index (property_name_p); + + ecma_value_t *argv_p = (ecma_value_t *) (arguments_p + 1); + + if (arguments_p->header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED) + { + argv_p = (ecma_value_t *) (((ecma_mapped_arguments_t *) object_p) + 1); + } + + JERRY_ASSERT (argv_p[index] == ECMA_VALUE_ARGUMENT_INITIALIZED + || argv_p[index] == ECMA_VALUE_ARGUMENT_NO_TRACK); + + argv_p[index] = ECMA_VALUE_EMPTY; +} /* ecma_op_arguments_delete_built_in_property */ + /** * List names of an arguments object's lazy instantiated properties */ void ecma_op_arguments_object_list_lazy_property_names (ecma_object_t *obj_p, /**< arguments object */ ecma_collection_t *prop_names_p, /**< prop name collection */ - ecma_property_counter_t *prop_counter_p) /**< prop counter */ + ecma_property_counter_t *prop_counter_p, /**< property counters */ + jerry_property_filter_t filter) /**< name filters */ { JERRY_ASSERT (ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_ARGUMENTS)); ecma_unmapped_arguments_t *arguments_p = (ecma_unmapped_arguments_t *) obj_p; - ecma_value_t *argv_p = (ecma_value_t *) (arguments_p + 1); uint32_t arguments_number = arguments_p->header.u.cls.u3.arguments_number; uint8_t flags = arguments_p->header.u.cls.u1.arguments_flags; - if (flags & ECMA_ARGUMENTS_OBJECT_MAPPED) + if (!(filter & JERRY_PROPERTY_FILTER_EXLCUDE_INTEGER_INDICES)) { - argv_p = (ecma_value_t *) (((ecma_mapped_arguments_t *) obj_p) + 1); - } + ecma_value_t *argv_p = (ecma_value_t *) (arguments_p + 1); - for (uint32_t index = 0; index < arguments_number; index++) - { - if (!ecma_is_value_empty (argv_p[index])) + if (flags & ECMA_ARGUMENTS_OBJECT_MAPPED) { - ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index); - ecma_collection_push_back (prop_names_p, ecma_make_string_value (index_string_p)); - prop_counter_p->array_index_named_props++; + argv_p = (ecma_value_t *) (((ecma_mapped_arguments_t *) obj_p) + 1); } - } - if (!(flags & ECMA_ARGUMENTS_OBJECT_LENGTH_INITIALIZED)) - { - ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); - prop_counter_p->string_named_props++; + for (uint32_t index = 0; index < arguments_number; index++) + { + if (!ecma_is_value_empty (argv_p[index])) + { + ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index); + ecma_collection_push_back (prop_names_p, ecma_make_string_value (index_string_p)); + prop_counter_p->array_index_named_props++; + } + } } - if (!(flags & ECMA_ARGUMENTS_OBJECT_CALLEE_INITIALIZED)) + if (!(filter & JERRY_PROPERTY_FILTER_EXLCUDE_STRINGS)) { - ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_CALLEE)); - prop_counter_p->string_named_props++; - } + if (!(flags & ECMA_ARGUMENTS_OBJECT_LENGTH_INITIALIZED)) + { + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); + prop_counter_p->string_named_props++; + } + + if (!(flags & ECMA_ARGUMENTS_OBJECT_CALLEE_INITIALIZED)) + { + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_CALLEE)); + prop_counter_p->string_named_props++; + } #if !JERRY_ESNEXT - if (!(flags & (ECMA_ARGUMENTS_OBJECT_CALLER_INITIALIZED | ECMA_ARGUMENTS_OBJECT_MAPPED))) - { - ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_CALLER)); - prop_counter_p->string_named_props++; + if (!(flags & ECMA_ARGUMENTS_OBJECT_MAPPED)) + { + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_CALLER)); + prop_counter_p->string_named_props++; + } +#endif /* !JERRY_ESNEXT */ } -#else /* JERRY_ESNEXT */ - if (!(flags & ECMA_ARGUMENTS_OBJECT_ITERATOR_INITIALIZED)) + +#if JERRY_ESNEXT + if (!(filter & JERRY_PROPERTY_FILTER_EXLCUDE_SYMBOLS) + && !(flags & ECMA_ARGUMENTS_OBJECT_ITERATOR_INITIALIZED)) { ecma_string_t *symbol_p = ecma_op_get_global_symbol (LIT_GLOBAL_SYMBOL_ITERATOR); ecma_collection_push_back (prop_names_p, ecma_make_symbol_value (symbol_p)); prop_counter_p->symbol_named_props++; } -#endif /* !JERRY_ESNEXT */ +#endif /* JERRY_ESNEXT */ } /* ecma_op_arguments_object_list_lazy_property_names */ /** diff --git a/jerry-core/ecma/operations/ecma-arguments-object.h b/jerry-core/ecma/operations/ecma-arguments-object.h index 46daed6846..08477582b3 100644 --- a/jerry-core/ecma/operations/ecma-arguments-object.h +++ b/jerry-core/ecma/operations/ecma-arguments-object.h @@ -23,8 +23,6 @@ ecma_value_t ecma_op_create_arguments_object (vm_frame_ctx_shared_args_t *shared_p, ecma_object_t *lex_env_p); -ecma_value_t -ecma_op_arguments_object_delete (ecma_object_t *object_p, ecma_string_t *property_name_p, bool is_throw); ecma_value_t ecma_op_arguments_object_define_own_property (ecma_object_t *object_p, ecma_string_t *property_name_p, const ecma_property_descriptor_t *property_desc_p); @@ -34,9 +32,12 @@ ecma_op_arguments_object_try_to_lazy_instantiate_property (ecma_object_t *object ecma_string_t *property_name_p); void -ecma_op_arguments_object_list_lazy_property_names (ecma_object_t *obj_p, - ecma_collection_t *prop_names_p, - ecma_property_counter_t *prop_counter_p); +ecma_op_arguments_delete_built_in_property (ecma_object_t *object_p, ecma_string_t *property_name_p); + +void +ecma_op_arguments_object_list_lazy_property_names (ecma_object_t *obj_p, ecma_collection_t *prop_names_p, + ecma_property_counter_t *prop_counter_p, + jerry_property_filter_t filter); ecma_string_t * ecma_op_arguments_object_get_formal_parameter (ecma_mapped_arguments_t *mapped_arguments_p, diff --git a/jerry-core/ecma/operations/ecma-array-object.c b/jerry-core/ecma/operations/ecma-array-object.c index 3be8f62c0f..f89e885cf0 100644 --- a/jerry-core/ecma/operations/ecma-array-object.c +++ b/jerry-core/ecma/operations/ecma-array-object.c @@ -649,32 +649,40 @@ ecma_fast_array_set_length (ecma_object_t *object_p, /**< fast access mode array * @return collection of strings - property names */ ecma_collection_t * -ecma_fast_array_object_own_property_keys (ecma_object_t *object_p) /**< fast access mode array object */ +ecma_fast_array_object_own_property_keys (ecma_object_t *object_p, /**< fast access mode array object */ + jerry_property_filter_t filter) /**< name filters */ { JERRY_ASSERT (ecma_op_object_is_fast_array (object_p)); - ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; ecma_collection_t *ret_p = ecma_new_collection (); - uint32_t length = ext_obj_p->u.array.length; - if (length != 0) + if (!(filter & JERRY_PROPERTY_FILTER_EXLCUDE_INTEGER_INDICES)) { - ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp); + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; + uint32_t length = ext_obj_p->u.array.length; - for (uint32_t i = 0; i < length; i++) + if (length != 0) { - if (ecma_is_value_array_hole (values_p[i])) + ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp); + + for (uint32_t i = 0; i < length; i++) { - continue; - } + if (ecma_is_value_array_hole (values_p[i])) + { + continue; + } - ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (i); + ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (i); - ecma_collection_push_back (ret_p, ecma_make_string_value (index_str_p)); + ecma_collection_push_back (ret_p, ecma_make_string_value (index_str_p)); + } } } - ecma_collection_push_back (ret_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); + if (!(filter & JERRY_PROPERTY_FILTER_EXLCUDE_STRINGS)) + { + ecma_collection_push_back (ret_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); + } return ret_p; } /* ecma_fast_array_object_own_property_keys */ diff --git a/jerry-core/ecma/operations/ecma-array-object.h b/jerry-core/ecma/operations/ecma-array-object.h index 2e6e8fe4e8..a56d3bc506 100644 --- a/jerry-core/ecma/operations/ecma-array-object.h +++ b/jerry-core/ecma/operations/ecma-array-object.h @@ -96,7 +96,7 @@ uint32_t ecma_delete_fast_array_properties (ecma_object_t *object_p, uint32_t new_length); ecma_collection_t * -ecma_fast_array_object_own_property_keys (ecma_object_t *object_p); +ecma_fast_array_object_own_property_keys (ecma_object_t *object_p, jerry_property_filter_t filter); void ecma_fast_array_convert_to_normal (ecma_object_t *object_p); diff --git a/jerry-core/ecma/operations/ecma-conversion.c b/jerry-core/ecma/operations/ecma-conversion.c index a217d30f20..de9781968c 100644 --- a/jerry-core/ecma/operations/ecma-conversion.c +++ b/jerry-core/ecma/operations/ecma-conversion.c @@ -1083,8 +1083,7 @@ ecma_op_to_index (ecma_value_t value, /**< ecma value */ */ ecma_collection_t * ecma_op_create_list_from_array_like (ecma_value_t arr, /**< array value */ - bool prop_names_only) /**< true - accept only property names - false - otherwise */ + uint32_t options) /**< from array like and property name filter flags */ { /* 1. */ JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (arr)); @@ -1095,10 +1094,12 @@ ecma_op_create_list_from_array_like (ecma_value_t arr, /**< array value */ ecma_raise_type_error (ECMA_ERR_MSG (ecma_error_argument_is_not_an_object)); return NULL; } + ecma_object_t *obj_p = ecma_get_object_from_value (arr); /* 4. 5. */ ecma_length_t len; + if (ECMA_IS_VALUE_ERROR (ecma_op_object_get_length (obj_p, &len))) { return NULL; @@ -1107,18 +1108,69 @@ ecma_op_create_list_from_array_like (ecma_value_t arr, /**< array value */ /* 6. */ ecma_collection_t *list_ptr = ecma_new_collection (); + if (!(options & ECMA_FROM_ARRAY_LIKE_ONLY_PROP_NAMES)) + { + /* 7. 8. */ + for (ecma_length_t idx = 0; idx < len; idx++) + { + ecma_value_t next = ecma_op_object_get_by_index (obj_p, idx); + + if (ECMA_IS_VALUE_ERROR (next)) + { + ecma_collection_free (list_ptr); + return NULL; + } + + ecma_collection_push_back (list_ptr, next); + } + + /* 9. */ + return list_ptr; + } + /* 7. 8. */ for (ecma_length_t idx = 0; idx < len; idx++) { ecma_value_t next = ecma_op_object_get_by_index (obj_p, idx); + if (ECMA_IS_VALUE_ERROR (next)) { ecma_collection_free (list_ptr); return NULL; } - if (prop_names_only - && !ecma_is_value_prop_name (next)) + if (ecma_is_value_string (next)) + { + jerry_property_filter_t non_symbol_mask = (JERRY_PROPERTY_FILTER_EXLCUDE_STRINGS + | JERRY_PROPERTY_FILTER_EXLCUDE_INTEGER_INDICES); + + if (options & non_symbol_mask) + { + if ((options & non_symbol_mask) == non_symbol_mask) + { + ecma_free_value (next); + continue; + } + + uint32_t index = ecma_string_get_array_index (ecma_get_string_from_value (next)); + + if ((index != ECMA_STRING_NOT_ARRAY_INDEX && (options & JERRY_PROPERTY_FILTER_EXLCUDE_INTEGER_INDICES)) + || (index == ECMA_STRING_NOT_ARRAY_INDEX && (options & JERRY_PROPERTY_FILTER_EXLCUDE_STRINGS))) + { + ecma_free_value (next); + continue; + } + } + } + else if (ecma_is_value_symbol (next)) + { + if (options & JERRY_PROPERTY_FILTER_EXLCUDE_SYMBOLS) + { + ecma_free_value (next); + continue; + } + } + else { ecma_free_value (next); ecma_collection_free (list_ptr); @@ -1132,6 +1184,7 @@ ecma_op_create_list_from_array_like (ecma_value_t arr, /**< array value */ /* 9. */ return list_ptr; } /* ecma_op_create_list_from_array_like */ + #endif /* JERRY_ESNEXT */ /** diff --git a/jerry-core/ecma/operations/ecma-conversion.h b/jerry-core/ecma/operations/ecma-conversion.h index 31c58eae12..114b5e1baf 100644 --- a/jerry-core/ecma/operations/ecma-conversion.h +++ b/jerry-core/ecma/operations/ecma-conversion.h @@ -47,6 +47,23 @@ typedef enum ECMA_TO_NUMERIC_ALLOW_BIGINT = (1 << 0), /**< allow BigInt values (ignored if BigInts are disabled) */ } ecma_to_numeric_options_t; +#if JERRY_ESNEXT + +/** + * Option bits for ecma_op_create_list_from_array_like. + */ +typedef enum +{ + ECMA_FROM_ARRAY_LIKE_ANY = 0, /**< copy all items of the array */ + ECMA_FROM_ARRAY_LIKE_ONLY_PROP_NAMES = (1 << 0), /**< only property names allowed */ + /* Further options: */ + /* JERRY_PROPERTY_FILTER_EXLCUDE_STRINGS */ + /* JERRY_PROPERTY_FILTER_EXLCUDE_SYMBOLS */ + /* JERRY_PROPERTY_FILTER_EXLCUDE_INTEGER_INDICES */ +} ecma_from_array_like_options_t; + +#endif /* JERRY_ESNEXT */ + bool ecma_op_require_object_coercible (ecma_value_t value); bool ecma_op_same_value (ecma_value_t x, ecma_value_t y); #if JERRY_BUILTIN_CONTAINER @@ -64,7 +81,7 @@ ecma_value_t ecma_op_to_integer (ecma_value_t value, ecma_number_t *number_p); ecma_value_t ecma_op_to_length (ecma_value_t value, ecma_length_t *length); #if JERRY_ESNEXT ecma_value_t ecma_op_to_index (ecma_value_t value, ecma_number_t *index); -ecma_collection_t *ecma_op_create_list_from_array_like (ecma_value_t arr, bool prop_names_only); +ecma_collection_t *ecma_op_create_list_from_array_like (ecma_value_t arr, uint32_t options); #endif /* JERRY_ESNEXT */ ecma_object_t *ecma_op_from_property_descriptor (const ecma_property_descriptor_t *src_prop_desc_p); diff --git a/jerry-core/ecma/operations/ecma-function-object.c b/jerry-core/ecma/operations/ecma-function-object.c index 7506397cf6..12985b00e7 100644 --- a/jerry-core/ecma/operations/ecma-function-object.c +++ b/jerry-core/ecma/operations/ecma-function-object.c @@ -2162,8 +2162,14 @@ ecma_op_bound_function_delete_built_in_property (ecma_object_t *object_p, /**< o void ecma_op_function_list_lazy_property_names (ecma_object_t *object_p, /**< functionobject */ ecma_collection_t *prop_names_p, /**< prop name collection */ - ecma_property_counter_t *prop_counter_p) /**< prop counter */ + ecma_property_counter_t *prop_counter_p, /**< property counters */ + jerry_property_filter_t filter) /**< name filters */ { + if (filter & JERRY_PROPERTY_FILTER_EXLCUDE_STRINGS) + { + return; + } + const ecma_compiled_code_t *bytecode_data_p; bytecode_data_p = ecma_op_function_get_compiled_code ((ecma_extended_object_t *) object_p); @@ -2236,21 +2242,19 @@ ecma_op_function_list_lazy_property_names (ecma_object_t *object_p, /**< functio void ecma_op_external_function_list_lazy_property_names (ecma_object_t *object_p, /**< function object */ ecma_collection_t *prop_names_p, /**< prop name collection */ - ecma_property_counter_t *prop_counter_p) /**< prop counter */ + ecma_property_counter_t *prop_counter_p, /**< property counters */ + jerry_property_filter_t filter) /**< name filters */ { -#if !JERRY_ESNEXT JERRY_UNUSED (object_p); -#else /* JERRY_ESNEXT */ - /* TODO: implicit class constructors need rework, and this code should be updated afterwards. */ - ecma_property_t *property_p = ecma_find_named_property (object_p, ecma_get_magic_string (LIT_MAGIC_STRING_PROTOTYPE)); - if (property_p == NULL || (*property_p & ECMA_PROPERTY_FLAG_BUILT_IN)) -#endif /* !JERRY_ESNEXT */ + if (filter & JERRY_PROPERTY_FILTER_EXLCUDE_STRINGS) { - /* 'prototype' property is non-enumerable (ECMA-262 v5, 13.2.18) */ - ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_PROTOTYPE)); - prop_counter_p->string_named_props++; + return; } + + /* 'prototype' property is non-enumerable (ECMA-262 v5, 13.2.18) */ + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_PROTOTYPE)); + prop_counter_p->string_named_props++; } /* ecma_op_external_function_list_lazy_property_names */ /** @@ -2263,8 +2267,14 @@ ecma_op_external_function_list_lazy_property_names (ecma_object_t *object_p, /** void ecma_op_bound_function_list_lazy_property_names (ecma_object_t *object_p, /**< bound function object*/ ecma_collection_t *prop_names_p, /**< prop name collection */ - ecma_property_counter_t *prop_counter_p) /**< prop counter */ + ecma_property_counter_t *prop_counter_p, /**< property counters */ + jerry_property_filter_t filter) /**< name filters */ { + if (filter & JERRY_PROPERTY_FILTER_EXLCUDE_STRINGS) + { + return; + } + #if JERRY_ESNEXT /* Unintialized 'length' property is non-enumerable (ECMA-262 v6, 19.2.4.1) */ ecma_bound_function_t *bound_func_p = (ecma_bound_function_t *) object_p; diff --git a/jerry-core/ecma/operations/ecma-function-object.h b/jerry-core/ecma/operations/ecma-function-object.h index 44b1963bb8..b2a710df68 100644 --- a/jerry-core/ecma/operations/ecma-function-object.h +++ b/jerry-core/ecma/operations/ecma-function-object.h @@ -117,19 +117,19 @@ ecma_op_bound_function_delete_built_in_property (ecma_object_t *object_p, ecma_s #endif /* JERRY_ESNEXT */ void -ecma_op_function_list_lazy_property_names (ecma_object_t *object_p, - ecma_collection_t *prop_names_p, - ecma_property_counter_t *prop_counter_p); +ecma_op_function_list_lazy_property_names (ecma_object_t *object_p, ecma_collection_t *prop_names_p, + ecma_property_counter_t *prop_counter_p, + jerry_property_filter_t filter); void -ecma_op_external_function_list_lazy_property_names (ecma_object_t *object_p, - ecma_collection_t *prop_names_p, - ecma_property_counter_t *prop_counter_p); +ecma_op_external_function_list_lazy_property_names (ecma_object_t *object_p, ecma_collection_t *prop_names_p, + ecma_property_counter_t *prop_counter_p, + jerry_property_filter_t filter); void -ecma_op_bound_function_list_lazy_property_names (ecma_object_t *object_p, - ecma_collection_t *prop_names_p, - ecma_property_counter_t *prop_counter_p); +ecma_op_bound_function_list_lazy_property_names (ecma_object_t *object_p, ecma_collection_t *prop_names_p, + ecma_property_counter_t *prop_counter_p, + jerry_property_filter_t filter); /** * @} diff --git a/jerry-core/ecma/operations/ecma-objects-general.c b/jerry-core/ecma/operations/ecma-objects-general.c index e9ec143ab2..91df8c36c0 100644 --- a/jerry-core/ecma/operations/ecma-objects-general.c +++ b/jerry-core/ecma/operations/ecma-objects-general.c @@ -13,6 +13,7 @@ * limitations under the License. */ +#include "ecma-arguments-object.h" #include "ecma-array-object.h" #include "ecma-builtins.h" #include "ecma-exceptions.h" @@ -151,6 +152,12 @@ ecma_op_general_object_delete (ecma_object_t *obj_p, /**< the object */ ecma_builtin_delete_built_in_property (obj_p, property_name_p); break; } + case ECMA_OBJECT_TYPE_CLASS: + { + JERRY_ASSERT (ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_ARGUMENTS)); + ecma_op_arguments_delete_built_in_property (obj_p, property_name_p); + break; + } case ECMA_OBJECT_TYPE_FUNCTION: { ecma_op_function_delete_built_in_property (obj_p, property_name_p); @@ -168,7 +175,15 @@ ecma_op_general_object_delete (ecma_object_t *obj_p, /**< the object */ } } #else /* !JERRY_ESNEXT */ - ecma_builtin_delete_built_in_property (obj_p, property_name_p); + if (type == ECMA_OBJECT_TYPE_CLASS) + { + JERRY_ASSERT (ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_ARGUMENTS)); + ecma_op_arguments_delete_built_in_property (obj_p, property_name_p); + } + else + { + ecma_builtin_delete_built_in_property (obj_p, property_name_p); + } #endif /* JERRY_ESNEXT */ } diff --git a/jerry-core/ecma/operations/ecma-objects.c b/jerry-core/ecma/operations/ecma-objects.c index 846631d05a..b745da7691 100644 --- a/jerry-core/ecma/operations/ecma-objects.c +++ b/jerry-core/ecma/operations/ecma-objects.c @@ -390,7 +390,8 @@ ecma_op_object_get_own_property (ecma_object_t *object_p, /**< the object */ ecma_value_t *argv_p = (ecma_value_t *) (mapped_arguments_p + 1); - if (!ecma_is_value_empty (argv_p[index])) + if (!ecma_is_value_empty (argv_p[index]) + && argv_p[index] != ECMA_VALUE_ARGUMENT_NO_TRACK) { #if JERRY_LCACHE /* Mapped arguments initialized properties MUST not be lcached */ @@ -585,7 +586,8 @@ ecma_op_object_find_own (ecma_value_t base_value, /**< base value */ ecma_value_t *argv_p = (ecma_value_t *) (mapped_arguments_p + 1); - if (!ecma_is_value_empty (argv_p[index])) + if (!ecma_is_value_empty (argv_p[index]) + && argv_p[index] != ECMA_VALUE_ARGUMENT_NO_TRACK) { ecma_string_t *name_p = ecma_op_arguments_object_get_formal_parameter (mapped_arguments_p, index); ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, mapped_arguments_p->lex_env); @@ -1428,7 +1430,8 @@ ecma_op_object_put_with_receiver (ecma_object_t *object_p, /**< the object */ ecma_value_t *argv_p = (ecma_value_t *) (mapped_arguments_p + 1); - if (!ecma_is_value_empty (argv_p[index])) + if (!ecma_is_value_empty (argv_p[index]) + && argv_p[index] != ECMA_VALUE_ARGUMENT_NO_TRACK) { ecma_string_t *name_p = ecma_op_arguments_object_get_formal_parameter (mapped_arguments_p, index); ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, mapped_arguments_p->lex_env); @@ -1812,13 +1815,6 @@ ecma_op_object_delete (ecma_object_t *obj_p, /**< the object */ && !ecma_is_lexical_environment (obj_p)); JERRY_ASSERT (property_name_p != NULL); - if (ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_ARGUMENTS)) - { - return ecma_op_arguments_object_delete (obj_p, - property_name_p, - is_strict); - } - #if JERRY_BUILTIN_PROXY if (ECMA_OBJECT_IS_PROXY (obj_p)) { @@ -2187,7 +2183,7 @@ ecma_op_object_get_enumerable_property_names (ecma_object_t *obj_p, /**< routine ecma_enumerable_property_names_options_t option) /**< listing option */ { /* 2. */ - ecma_collection_t *prop_names_p = ecma_op_object_own_property_keys (obj_p); + ecma_collection_t *prop_names_p = ecma_op_object_own_property_keys (obj_p, JERRY_PROPERTY_FILTER_EXLCUDE_SYMBOLS); #if JERRY_BUILTIN_PROXY if (JERRY_UNLIKELY (prop_names_p == NULL)) @@ -2279,34 +2275,14 @@ ecma_op_object_get_enumerable_property_names (ecma_object_t *obj_p, /**< routine return properties_p; } /* ecma_op_object_get_enumerable_property_names */ -/** - * Helper method to check if a given property is already in the collection or not - * - * @return true - if the property is already in the collection - * false - otherwise - */ -static bool -ecma_object_prop_name_is_duplicated (ecma_collection_t *prop_names_p, /**< prop name collection */ - ecma_string_t *name_p) /**< property name */ -{ - for (uint64_t i = 0; i < prop_names_p->item_count; i++) - { - if (ecma_compare_ecma_strings (ecma_get_prop_name_from_value (prop_names_p->buffer_p[i]), name_p)) - { - return true; - } - } - - return false; -} /* ecma_object_prop_name_is_duplicated */ - /** * Helper method for getting lazy instantiated properties for [[OwnPropertyKeys]] */ static void ecma_object_list_lazy_property_names (ecma_object_t *obj_p, /**< object */ ecma_collection_t *prop_names_p, /**< prop name collection */ - ecma_property_counter_t *prop_counter_p) /**< prop counter */ + ecma_property_counter_t *prop_counter_p, /**< property counters */ + jerry_property_filter_t filter) /**< name filters */ { switch (ecma_get_object_type (obj_p)) { @@ -2314,7 +2290,7 @@ ecma_object_list_lazy_property_names (ecma_object_t *obj_p, /**< object */ { if (ecma_builtin_function_is_routine (obj_p)) { - ecma_builtin_routine_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p); + ecma_builtin_routine_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p, filter); break; } /* FALLTHRU */ @@ -2323,7 +2299,7 @@ ecma_object_list_lazy_property_names (ecma_object_t *obj_p, /**< object */ case ECMA_OBJECT_TYPE_BUILT_IN_CLASS: case ECMA_OBJECT_TYPE_BUILT_IN_ARRAY: { - ecma_builtin_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p); + ecma_builtin_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p, filter); break; } case ECMA_OBJECT_TYPE_CLASS: @@ -2334,19 +2310,19 @@ ecma_object_list_lazy_property_names (ecma_object_t *obj_p, /**< object */ { case ECMA_OBJECT_CLASS_STRING: { - ecma_op_string_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p); + ecma_op_string_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p, filter); break; } case ECMA_OBJECT_CLASS_ARGUMENTS: { - ecma_op_arguments_object_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p); + ecma_op_arguments_object_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p, filter); break; } #if JERRY_BUILTIN_TYPEDARRAY /* ES2015 9.4.5.1 */ case ECMA_OBJECT_CLASS_TYPEDARRAY: { - ecma_op_typedarray_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p); + ecma_op_typedarray_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p, filter); break; } #endif /* JERRY_BUILTIN_TYPEDARRAY */ @@ -2355,23 +2331,26 @@ ecma_object_list_lazy_property_names (ecma_object_t *obj_p, /**< object */ } case ECMA_OBJECT_TYPE_FUNCTION: { - ecma_op_function_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p); + ecma_op_function_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p, filter); break; } case ECMA_OBJECT_TYPE_NATIVE_FUNCTION: { - ecma_op_external_function_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p); + ecma_op_external_function_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p, filter); break; } case ECMA_OBJECT_TYPE_BOUND_FUNCTION: { - ecma_op_bound_function_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p); + ecma_op_bound_function_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p, filter); break; } case ECMA_OBJECT_TYPE_ARRAY: { - ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); - prop_counter_p->string_named_props++; + if (!(filter & JERRY_PROPERTY_FILTER_EXLCUDE_STRINGS)) + { + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); + prop_counter_p->string_named_props++; + } break; } default: @@ -2384,171 +2363,166 @@ ecma_object_list_lazy_property_names (ecma_object_t *obj_p, /**< object */ } /* ecma_object_list_lazy_property_names */ /** - * Helper method for sorting the given property names based on [[OwnPropertyKeys]] + * Object's [[OwnPropertyKeys]] internal method + * + * Order of names in the collection: + * - integer indices in ascending order + * - other indices in creation order (for built-ins: the order of 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 NULL - if the Proxy.[[OwnPropertyKeys]] operation raises error + * collection of property names - otherwise */ -static void -ecma_object_sort_property_names (ecma_collection_t *prop_names_p, /**< prop name collection */ - ecma_property_counter_t *prop_counter) /**< prop counter */ +ecma_collection_t * +ecma_op_object_own_property_keys (ecma_object_t *obj_p, /**< object */ + jerry_property_filter_t filter) /**< name filters */ { - uint32_t lazy_string_prop_name_count = prop_counter->lazy_string_named_props; -#if JERRY_ESNEXT - uint32_t lazy_symbol_prop_name_count = prop_counter->lazy_symbol_named_props; -#endif /* JERRY_ESNEXT */ +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (obj_p)) + { + return ecma_proxy_object_own_property_keys (obj_p, filter); + } +#endif /* JERRY_BUILTIN_PROXY */ - uint32_t string_name_pos = prop_counter->string_named_props; -#if JERRY_ESNEXT - uint32_t symbol_name_pos = prop_counter->symbol_named_props; -#endif /* JERRY_ESNEXT */ + if (ecma_op_object_is_fast_array (obj_p)) + { + return ecma_fast_array_object_own_property_keys (obj_p, filter); + } - uint32_t all_prop_count = (prop_counter->array_index_named_props) + (string_name_pos); -#if JERRY_ESNEXT - all_prop_count += symbol_name_pos; -#endif /* JERRY_ESNEXT */ + ecma_collection_t *prop_names_p = ecma_new_collection (); + ecma_property_counter_t prop_counter = {0, 0, 0}; - ecma_value_t *names_p = jmem_heap_alloc_block (all_prop_count * sizeof (ecma_value_t)); + ecma_object_list_lazy_property_names (obj_p, prop_names_p, &prop_counter, filter); - ecma_value_t *string_names_p = names_p + prop_counter->array_index_named_props; -#if JERRY_ESNEXT - ecma_value_t *symbol_names_p = string_names_p + string_name_pos; -#endif /* JERRY_ESNEXT */ + jmem_cpointer_t prop_iter_cp = obj_p->u1.property_list_cp; + +#if JERRY_PROPERTY_HASHMAP + if (prop_iter_cp != JMEM_CP_NULL) + { + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); - uint32_t array_index_name_pos = 0; - uint32_t lazy_string_name_pos = 0; + if (prop_iter_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP) + { + prop_iter_cp = prop_iter_p->next_property_cp; + } + } +#endif /* JERRY_PROPERTY_HASHMAP */ + + jmem_cpointer_t counter_prop_iter_cp = prop_iter_cp; + + uint32_t array_index_named_props = 0; + uint32_t string_named_props = 0; #if JERRY_ESNEXT - uint32_t lazy_symbol_name_pos = 0; + uint32_t symbol_named_props = 0; #endif /* JERRY_ESNEXT */ - for (uint32_t i = 0; i < prop_names_p->item_count; i++) + while (counter_prop_iter_cp != JMEM_CP_NULL) { - ecma_value_t prop_name = prop_names_p->buffer_p[i]; - ecma_string_t *name_p = ecma_get_prop_name_from_value (prop_name); - uint32_t index = ecma_string_get_array_index (name_p); + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, counter_prop_iter_cp); + JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); - /* sort array index named properties in ascending order */ - if (index != ECMA_STRING_NOT_ARRAY_INDEX) + for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) { - JERRY_ASSERT (array_index_name_pos < prop_counter->array_index_named_props); + ecma_property_t *property_p = prop_iter_p->types + i; - uint32_t insert_pos = 0; - while (insert_pos < array_index_name_pos - && index > ecma_string_get_array_index (ecma_get_string_from_value (names_p[insert_pos]))) + if (!ECMA_PROPERTY_IS_RAW (*property_p) + || (*property_p & ECMA_PROPERTY_FLAG_BUILT_IN)) { - insert_pos++; + continue; } - if (insert_pos == array_index_name_pos) + ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p; + + if (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_DIRECT_STRING_MAGIC + && prop_pair_p->names_cp[i] >= LIT_NON_INTERNAL_MAGIC_STRING__COUNT + && prop_pair_p->names_cp[i] < LIT_MAGIC_STRING__COUNT) { - names_p[array_index_name_pos++] = prop_name; + continue; } - else - { - JERRY_ASSERT (insert_pos < array_index_name_pos); - JERRY_ASSERT (index <= ecma_string_get_array_index (ecma_get_string_from_value (names_p[insert_pos]))); - uint32_t move_pos = array_index_name_pos++; + ecma_string_t *name_p = ecma_string_from_property_name (*property_p, + prop_pair_p->names_cp[i]); - while (move_pos > insert_pos) - { - names_p[move_pos] = names_p[move_pos - 1u]; - - move_pos--; - } - - names_p[insert_pos] = prop_name; - } - } -#if JERRY_ESNEXT - /* sort symbol named properites in creation order */ - else if (ecma_prop_name_is_symbol (name_p)) - { - JERRY_ASSERT (symbol_name_pos > 0); - JERRY_ASSERT (symbol_name_pos <= prop_counter->symbol_named_props); - - if (i < lazy_symbol_prop_name_count) + if (ecma_string_get_array_index (name_p) != ECMA_STRING_NOT_ARRAY_INDEX) { - symbol_names_p[lazy_symbol_name_pos++] = prop_name; + array_index_named_props++; } - else +#if JERRY_ESNEXT + else if (ecma_prop_name_is_symbol (name_p)) { - symbol_names_p[--symbol_name_pos] = prop_name; + symbol_named_props++; } - } #endif /* JERRY_ESNEXT */ - /* sort string named properties in creation order */ - else - { - JERRY_ASSERT (string_name_pos > 0); - JERRY_ASSERT (string_name_pos <= prop_counter->string_named_props); - - if (i < lazy_string_prop_name_count) - { - string_names_p[lazy_string_name_pos++] = prop_name; - } else { - string_names_p[--string_name_pos] = prop_name; + string_named_props++; } + + ecma_deref_ecma_string (name_p); } + + counter_prop_iter_cp = prop_iter_p->next_property_cp; } - /* Free the unsorted buffer and copy the sorted one in its place */ - jmem_heap_free_block (prop_names_p->buffer_p, ECMA_COLLECTION_ALLOCATED_SIZE (prop_names_p->capacity)); - prop_names_p->buffer_p = names_p; - prop_names_p->item_count = all_prop_count; - prop_names_p->capacity = all_prop_count; -} /* ecma_object_sort_property_names */ + if (filter & JERRY_PROPERTY_FILTER_EXLCUDE_INTEGER_INDICES) + { + JERRY_ASSERT (prop_counter.array_index_named_props == 0); + array_index_named_props = 0; + } -/** - * Object's [[OwnPropertyKeys]] internal method - * - * Order of names in the collection: - * - integer indices in ascending order - * - other indices in creation order (for built-ins: the order of 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 NULL - if the Proxy.[[OwnPropertyKeys]] operation raises error - * collection of property names - otherwise - */ -ecma_collection_t * -ecma_op_object_own_property_keys (ecma_object_t *obj_p) /**< object */ -{ -#if JERRY_BUILTIN_PROXY - if (ECMA_OBJECT_IS_PROXY (obj_p)) + if (filter & JERRY_PROPERTY_FILTER_EXLCUDE_STRINGS) { - return ecma_proxy_object_own_property_keys (obj_p); + JERRY_ASSERT (prop_counter.string_named_props == 0); + string_named_props = 0; } -#endif /* JERRY_BUILTIN_PROXY */ - if (ecma_op_object_is_fast_array (obj_p)) +#if JERRY_ESNEXT + if (filter & JERRY_PROPERTY_FILTER_EXLCUDE_SYMBOLS) { - return ecma_fast_array_object_own_property_keys (obj_p); + JERRY_ASSERT (prop_counter.symbol_named_props == 0); + symbol_named_props = 0; } - ecma_collection_t *prop_names_p = ecma_new_collection (); - ecma_property_counter_t prop_counter = {0, 0, 0, 0, 0}; + uint32_t total = array_index_named_props + string_named_props + symbol_named_props; +#else /* !JERRY_ESNEXT */ + uint32_t total = array_index_named_props + string_named_props; +#endif /* JERRY_ESNEXT */ + + if (total == 0) + { + return prop_names_p; + } - ecma_object_list_lazy_property_names (obj_p, prop_names_p, &prop_counter); + ecma_collection_reserve (prop_names_p, total); + prop_names_p->item_count += total; - prop_counter.lazy_string_named_props = prop_names_p->item_count - prop_counter.symbol_named_props; - prop_counter.lazy_symbol_named_props = prop_counter.symbol_named_props; + ecma_value_t *buffer_p = prop_names_p->buffer_p; + ecma_value_t *array_index_current_p = buffer_p + array_index_named_props + prop_counter.array_index_named_props; + ecma_value_t *string_current_p = array_index_current_p + string_named_props + prop_counter.string_named_props; - jmem_cpointer_t prop_iter_cp = obj_p->u1.property_list_cp; +#if JERRY_ESNEXT + ecma_value_t *symbol_current_p = string_current_p + symbol_named_props + prop_counter.symbol_named_props; -#if JERRY_PROPERTY_HASHMAP - if (prop_iter_cp != JMEM_CP_NULL) + if (prop_counter.symbol_named_props > 0 + && (array_index_named_props + string_named_props) > 0) { - ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + memmove ((void *) string_current_p, + (void *) (buffer_p + prop_counter.array_index_named_props + prop_counter.string_named_props), + prop_counter.symbol_named_props * sizeof (ecma_value_t)); + } +#endif /* JERRY_ESNEXT */ - if (prop_iter_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP) - { - prop_iter_cp = prop_iter_p->next_property_cp; - } + if (prop_counter.string_named_props > 0 + && array_index_named_props > 0) + { + memmove ((void *) array_index_current_p, + (void *) (buffer_p + prop_counter.array_index_named_props), + prop_counter.string_named_props * sizeof (ecma_value_t)); } -#endif /* JERRY_PROPERTY_HASHMAP */ while (prop_iter_cp != JMEM_CP_NULL) { @@ -2559,55 +2533,57 @@ ecma_op_object_own_property_keys (ecma_object_t *obj_p) /**< object */ { ecma_property_t *property_p = prop_iter_p->types + i; - if (ECMA_PROPERTY_IS_RAW (*property_p) - && !(*property_p & ECMA_PROPERTY_FLAG_BUILT_IN)) + if (!ECMA_PROPERTY_IS_RAW (*property_p) + || (*property_p & ECMA_PROPERTY_FLAG_BUILT_IN)) { - ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p; + continue; + } + + ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p; + + if (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_DIRECT_STRING_MAGIC + && prop_pair_p->names_cp[i] >= LIT_NON_INTERNAL_MAGIC_STRING__COUNT + && prop_pair_p->names_cp[i] < LIT_MAGIC_STRING__COUNT) + { + continue; + } - if (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_DIRECT_STRING_MAGIC - && prop_pair_p->names_cp[i] >= LIT_NON_INTERNAL_MAGIC_STRING__COUNT - && prop_pair_p->names_cp[i] < LIT_MAGIC_STRING__COUNT) + ecma_string_t *name_p = ecma_string_from_property_name (*property_p, + prop_pair_p->names_cp[i]); + + if (ecma_string_get_array_index (name_p) != ECMA_STRING_NOT_ARRAY_INDEX) + { + if (!(filter & JERRY_PROPERTY_FILTER_EXLCUDE_INTEGER_INDICES)) { + *(--array_index_current_p) = ecma_make_string_value (name_p); continue; } - - ecma_string_t *name_p = ecma_string_from_property_name (*property_p, - prop_pair_p->names_cp[i]); - - if (!ecma_object_prop_name_is_duplicated (prop_names_p, name_p)) + } +#if JERRY_ESNEXT + else if (ecma_prop_name_is_symbol (name_p)) + { + if (!(filter & JERRY_PROPERTY_FILTER_EXLCUDE_SYMBOLS)) { - if (ecma_string_get_array_index (name_p) != ECMA_STRING_NOT_ARRAY_INDEX) - { - prop_counter.array_index_named_props++; - } - #if JERRY_ESNEXT - else if (ecma_prop_name_is_symbol (name_p)) - { - prop_counter.symbol_named_props++; - } - #endif /* JERRY_ESNEXT */ - else - { - prop_counter.string_named_props++; - } - - ecma_collection_push_back (prop_names_p, ecma_make_prop_name_value (name_p)); + *(--symbol_current_p) = ecma_make_symbol_value (name_p); + continue; } - else + } +#endif /* JERRY_ESNEXT */ + else + { + if (!(filter & JERRY_PROPERTY_FILTER_EXLCUDE_STRINGS)) { - ecma_deref_ecma_string (name_p); + *(--string_current_p) = ecma_make_string_value (name_p); + continue; } } + + ecma_deref_ecma_string (name_p); } prop_iter_cp = prop_iter_p->next_property_cp; } - if (prop_names_p->item_count != 0) - { - ecma_object_sort_property_names (prop_names_p, &prop_counter); - } - return prop_names_p; } /* ecma_op_object_own_property_keys */ @@ -2630,7 +2606,7 @@ ecma_op_object_enumerate (ecma_object_t *obj_p) /**< object */ while (true) { - ecma_collection_t *keys = ecma_op_object_own_property_keys (obj_p); + ecma_collection_t *keys = ecma_op_object_own_property_keys (obj_p, JERRY_PROPERTY_FILTER_EXLCUDE_SYMBOLS); #if JERRY_ESNEXT if (JERRY_UNLIKELY (keys == NULL)) @@ -2647,13 +2623,6 @@ ecma_op_object_enumerate (ecma_object_t *obj_p) /**< object */ ecma_value_t prop_name = keys->buffer_p[i]; ecma_string_t *name_p = ecma_get_prop_name_from_value (prop_name); -#if JERRY_ESNEXT - if (ecma_prop_name_is_symbol (name_p)) - { - continue; - } -#endif /* JERRY_ESNEXT */ - ecma_property_descriptor_t prop_desc; ecma_value_t get_desc = ecma_op_object_get_own_property_descriptor (obj_p, name_p, &prop_desc); diff --git a/jerry-core/ecma/operations/ecma-objects.h b/jerry-core/ecma/operations/ecma-objects.h index 26f78352cc..4e1336524c 100644 --- a/jerry-core/ecma/operations/ecma-objects.h +++ b/jerry-core/ecma/operations/ecma-objects.h @@ -97,7 +97,7 @@ ecma_object_t *ecma_op_object_get_prototype_of (ecma_object_t *obj_p); ecma_value_t ecma_op_object_is_prototype_of (ecma_object_t *base_p, ecma_object_t *target_p); ecma_collection_t * ecma_op_object_get_enumerable_property_names (ecma_object_t *obj_p, ecma_enumerable_property_names_options_t option); -ecma_collection_t *ecma_op_object_own_property_keys (ecma_object_t *obj_p); +ecma_collection_t *ecma_op_object_own_property_keys (ecma_object_t *obj_p, jerry_property_filter_t filter); ecma_collection_t *ecma_op_object_enumerate (ecma_object_t *obj_p); lit_magic_string_id_t ecma_object_get_class_name (ecma_object_t *obj_p); diff --git a/jerry-core/ecma/operations/ecma-proxy-object.c b/jerry-core/ecma/operations/ecma-proxy-object.c index 5fcc1dcb41..f21c877976 100644 --- a/jerry-core/ecma/operations/ecma-proxy-object.c +++ b/jerry-core/ecma/operations/ecma-proxy-object.c @@ -1604,7 +1604,8 @@ ecma_proxy_check_invariants_for_own_prop_keys (ecma_collection_t *trap_result, * pointer to a newly allocated list of property names - otherwise */ ecma_collection_t * -ecma_proxy_object_own_property_keys (ecma_object_t *obj_p) /**< proxy object */ +ecma_proxy_object_own_property_keys (ecma_object_t *obj_p, /**< proxy object */ + jerry_property_filter_t filter) /**< name filters */ { JERRY_ASSERT (ECMA_OBJECT_IS_PROXY (obj_p)); ECMA_CHECK_STACK_USAGE_RETURN (NULL); @@ -1628,7 +1629,7 @@ ecma_proxy_object_own_property_keys (ecma_object_t *obj_p) /**< proxy object */ /* 6. */ if (ecma_is_value_undefined (trap)) { - ecma_collection_t *result = ecma_op_object_own_property_keys (target_obj_p); + ecma_collection_t *result = ecma_op_object_own_property_keys (target_obj_p, filter); JERRY_BLOCK_TAIL_CALL_OPTIMIZATION (); return result; } @@ -1646,7 +1647,8 @@ ecma_proxy_object_own_property_keys (ecma_object_t *obj_p) /**< proxy object */ } /* 8. */ - ecma_collection_t *trap_result = ecma_op_create_list_from_array_like (trap_result_array, true); + uint32_t options = ECMA_FROM_ARRAY_LIKE_ONLY_PROP_NAMES; + ecma_collection_t *trap_result = ecma_op_create_list_from_array_like (trap_result_array, options | filter); ecma_free_value (trap_result_array); @@ -1674,7 +1676,7 @@ ecma_proxy_object_own_property_keys (ecma_object_t *obj_p) /**< proxy object */ } /* 11. */ - ecma_collection_t *target_keys = ecma_op_object_own_property_keys (target_obj_p); + ecma_collection_t *target_keys = ecma_op_object_own_property_keys (target_obj_p, filter); if (target_keys == NULL) { diff --git a/jerry-core/ecma/operations/ecma-proxy-object.h b/jerry-core/ecma/operations/ecma-proxy-object.h index 1fa235226d..2332c43f46 100644 --- a/jerry-core/ecma/operations/ecma-proxy-object.h +++ b/jerry-core/ecma/operations/ecma-proxy-object.h @@ -92,7 +92,7 @@ ecma_proxy_object_delete_property (ecma_object_t *obj_p, bool is_strict); ecma_collection_t * -ecma_proxy_object_own_property_keys (ecma_object_t *obj_p); +ecma_proxy_object_own_property_keys (ecma_object_t *obj_p, jerry_property_filter_t filter); ecma_value_t ecma_proxy_object_call (ecma_object_t *obj_p, diff --git a/jerry-core/ecma/operations/ecma-string-object.c b/jerry-core/ecma/operations/ecma-string-object.c index cf4c363dd8..435a696fd4 100644 --- a/jerry-core/ecma/operations/ecma-string-object.c +++ b/jerry-core/ecma/operations/ecma-string-object.c @@ -105,29 +105,36 @@ 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 */ ecma_collection_t *prop_names_p, /**< prop name collection */ - ecma_property_counter_t *prop_counter_p) /**< prop counter */ + ecma_property_counter_t *prop_counter_p, /**< property counters */ + jerry_property_filter_t filter) /**< name filters */ { JERRY_ASSERT (ecma_get_object_base_type (obj_p) == ECMA_OBJECT_BASE_TYPE_CLASS); - ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; - JERRY_ASSERT (ext_object_p->u.cls.type == ECMA_OBJECT_CLASS_STRING); + if (!(filter & JERRY_PROPERTY_FILTER_EXLCUDE_INTEGER_INDICES)) + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; + JERRY_ASSERT (ext_object_p->u.cls.type == ECMA_OBJECT_CLASS_STRING); - ecma_string_t *prim_value_str_p = ecma_get_string_from_value (ext_object_p->u.cls.u3.value); + ecma_string_t *prim_value_str_p = ecma_get_string_from_value (ext_object_p->u.cls.u3.value); - lit_utf8_size_t length = ecma_string_get_length (prim_value_str_p); + lit_utf8_size_t length = ecma_string_get_length (prim_value_str_p); - for (lit_utf8_size_t i = 0; i < length; i++) - { - ecma_string_t *name_p = ecma_new_ecma_string_from_uint32 (i); + for (lit_utf8_size_t i = 0; i < length; i++) + { + ecma_string_t *name_p = ecma_new_ecma_string_from_uint32 (i); - /* the properties are enumerable (ECMA-262 v5, 15.5.5.2.9) */ - ecma_collection_push_back (prop_names_p, ecma_make_string_value (name_p)); - } + /* the properties are enumerable (ECMA-262 v5, 15.5.5.2.9) */ + ecma_collection_push_back (prop_names_p, ecma_make_string_value (name_p)); + } - prop_counter_p->array_index_named_props += length; + prop_counter_p->array_index_named_props += length; + } - ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); - prop_counter_p->string_named_props++; + if (!(filter & JERRY_PROPERTY_FILTER_EXLCUDE_STRINGS)) + { + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); + prop_counter_p->string_named_props++; + } } /* 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 4ce1d44323..da0d7431ce 100644 --- a/jerry-core/ecma/operations/ecma-string-object.h +++ b/jerry-core/ecma/operations/ecma-string-object.h @@ -29,9 +29,9 @@ ecma_value_t ecma_op_create_string_object (const ecma_value_t *arguments_list_p, uint32_t arguments_list_len); void -ecma_op_string_list_lazy_property_names (ecma_object_t *obj_p, - ecma_collection_t *prop_names_p, - ecma_property_counter_t *prop_counter_p); +ecma_op_string_list_lazy_property_names (ecma_object_t *obj_p, ecma_collection_t *prop_names_p, + ecma_property_counter_t *prop_counter_p, + jerry_property_filter_t filter); /** * @} diff --git a/jerry-core/ecma/operations/ecma-typedarray-object.c b/jerry-core/ecma/operations/ecma-typedarray-object.c index 62be35f8c1..2a48299711 100644 --- a/jerry-core/ecma/operations/ecma-typedarray-object.c +++ b/jerry-core/ecma/operations/ecma-typedarray-object.c @@ -1827,10 +1827,16 @@ ecma_is_typedarray (ecma_value_t value) /**< the target need to be checked */ void ecma_op_typedarray_list_lazy_property_names (ecma_object_t *obj_p, /**< a TypedArray object */ ecma_collection_t *prop_names_p, /**< prop name collection */ - ecma_property_counter_t *prop_counter_p) /**< prop counter */ + ecma_property_counter_t *prop_counter_p, /**< property counters */ + jerry_property_filter_t filter) /**< name filters */ { JERRY_ASSERT (ecma_object_is_typedarray (obj_p)); + if (filter & JERRY_PROPERTY_FILTER_EXLCUDE_INTEGER_INDICES) + { + return; + } + uint32_t array_length = ecma_typedarray_get_length (obj_p); for (uint32_t i = 0; i < array_length; i++) diff --git a/jerry-core/ecma/operations/ecma-typedarray-object.h b/jerry-core/ecma/operations/ecma-typedarray-object.h index b3b9c78421..4cbc1965fe 100644 --- a/jerry-core/ecma/operations/ecma-typedarray-object.h +++ b/jerry-core/ecma/operations/ecma-typedarray-object.h @@ -62,9 +62,9 @@ ecma_typedarray_iterators_helper (ecma_value_t this_arg, ecma_iterator_kind_t ki bool ecma_object_is_typedarray (ecma_object_t *obj_p); bool ecma_is_typedarray (ecma_value_t target); -void ecma_op_typedarray_list_lazy_property_names (ecma_object_t *obj_p, - ecma_collection_t *prop_names_p, - ecma_property_counter_t *prop_counter_p); +void ecma_op_typedarray_list_lazy_property_names (ecma_object_t *obj_p, ecma_collection_t *prop_names_p, + ecma_property_counter_t *prop_counter_p, + jerry_property_filter_t filter); ecma_value_t ecma_op_typedarray_define_own_property (ecma_object_t *obj_p, ecma_string_t *prop_name_p, const ecma_property_descriptor_t *property_desc_p); diff --git a/jerry-core/vm/opcodes.c b/jerry-core/vm/opcodes.c index 4ad26b1a5d..e8e5ae48b8 100644 --- a/jerry-core/vm/opcodes.c +++ b/jerry-core/vm/opcodes.c @@ -1558,7 +1558,7 @@ opfunc_copy_data_properties (ecma_value_t target_object, /**< target object */ } ecma_object_t *source_object_p = ecma_get_object_from_value (source_object); - ecma_collection_t *names_p = ecma_op_object_own_property_keys (source_object_p); + ecma_collection_t *names_p = ecma_op_object_own_property_keys (source_object_p, JERRY_PROPERTY_FILTER_ALL); #if JERRY_BUILTIN_PROXY if (names_p == NULL)