From b2a2022d0a5c1d2151911f3432e9cd6321604030 Mon Sep 17 00:00:00 2001 From: Robert Fancsik Date: Mon, 25 May 2020 13:00:21 +0200 Subject: [PATCH] Fix property order in lazy property listing for builtin/external functions (#3780) JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu --- .../ecma/operations/ecma-function-object.c | 14 +++++++++++--- .../ecma/operations/ecma-function-object.h | 3 ++- jerry-core/ecma/operations/ecma-objects.c | 16 +++++++++++++--- jerry-core/vm/opcodes.c | 12 ++++++++++-- tests/jerry/es2015/regression-test-issue-3606.js | 2 +- 5 files changed, 37 insertions(+), 10 deletions(-) diff --git a/jerry-core/ecma/operations/ecma-function-object.c b/jerry-core/ecma/operations/ecma-function-object.c index 9cca4ab9f..5a4431220 100644 --- a/jerry-core/ecma/operations/ecma-function-object.c +++ b/jerry-core/ecma/operations/ecma-function-object.c @@ -1649,7 +1649,8 @@ 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 (uint32_t opts, /**< listing options using flags +ecma_op_external_function_list_lazy_property_names (ecma_object_t *object_p, /**< function object */ + 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 @@ -1659,8 +1660,15 @@ ecma_op_external_function_list_lazy_property_names (uint32_t opts, /**< listing 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)); +#if !ENABLED (JERRY_ES2015) + JERRY_UNUSED (object_p); +#else /* ENABLED (JERRY_ES2015) */ + if (!ecma_op_ordinary_object_has_own_property (object_p, ecma_get_magic_string (LIT_MAGIC_STRING_PROTOTYPE))) +#endif /* !ENABLED (JERRY_ES2015) */ + { + /* '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)); + } } /* ecma_op_external_function_list_lazy_property_names */ /** diff --git a/jerry-core/ecma/operations/ecma-function-object.h b/jerry-core/ecma/operations/ecma-function-object.h index b5aaede3d..25e47461f 100644 --- a/jerry-core/ecma/operations/ecma-function-object.h +++ b/jerry-core/ecma/operations/ecma-function-object.h @@ -94,7 +94,8 @@ ecma_op_function_list_lazy_property_names (ecma_object_t *object_p, ecma_collection_t *non_enum_collection_p); void -ecma_op_external_function_list_lazy_property_names (uint32_t opts, +ecma_op_external_function_list_lazy_property_names (ecma_object_t *object_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-objects.c b/jerry-core/ecma/operations/ecma-objects.c index 649764871..f76cd7833 100644 --- a/jerry-core/ecma/operations/ecma-objects.c +++ b/jerry-core/ecma/operations/ecma-objects.c @@ -2108,7 +2108,8 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */ { if (!is_array_indices_only) { - ecma_op_external_function_list_lazy_property_names (opts, + ecma_op_external_function_list_lazy_property_names (obj_p, + opts, prop_names_p, skipped_non_enumerable_p); } @@ -2160,6 +2161,7 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */ #endif /* ENABLED (JERRY_ES2015) */ ecma_value_t *buffer_p = prop_names_p->buffer_p; + uint32_t lazy_prop_name_count = prop_names_p->item_count; const size_t own_names_hashes_bitmap_size = ECMA_OBJECT_HASH_BITMAP_SIZE / bitmap_row_size; JERRY_VLA (uint32_t, own_names_hashes_bitmap, own_names_hashes_bitmap_size); @@ -2392,6 +2394,7 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */ uint32_t array_index_name_pos = 0; uint32_t string_name_pos = string_named_properties_count; + uint32_t lazy_string_name_pos = 0; #if ENABLED (JERRY_ES2015) uint32_t symbol_name_pos = symbol_named_properties_count; #endif /* ENABLED (JERRY_ES2015) */ @@ -2453,12 +2456,19 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */ JERRY_ASSERT (string_name_pos > 0); JERRY_ASSERT (string_name_pos <= string_named_properties_count); - string_names_p[--string_name_pos] = name_p; + if (i < lazy_prop_name_count) + { + string_names_p[lazy_string_name_pos++] = name_p; + } + else + { + string_names_p[--string_name_pos] = name_p; + } } } JERRY_ASSERT (array_index_name_pos == array_index_named_properties_count); - JERRY_ASSERT (string_name_pos == 0); + JERRY_ASSERT (string_name_pos - lazy_string_name_pos == 0); #if ENABLED (JERRY_ES2015) JERRY_ASSERT (symbol_name_pos == 0); #endif /* ENABLED (JERRY_ES2015) */ diff --git a/jerry-core/vm/opcodes.c b/jerry-core/vm/opcodes.c index e8c0ccc8f..da24309dd 100644 --- a/jerry-core/vm/opcodes.c +++ b/jerry-core/vm/opcodes.c @@ -867,6 +867,14 @@ opfunc_create_implicit_class_constructor (uint8_t opcode) /**< current cbc opcod ext_func_obj_p->u.external_handler_cb = ecma_op_implicit_constructor_handler_cb; } + ecma_property_value_t *prop_value_p; + prop_value_p = ecma_create_named_data_property (func_obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH), + ECMA_PROPERTY_FLAG_CONFIGURABLE, + NULL); + + prop_value_p->value = ecma_make_uint32_value (0); + return ecma_make_object_value (func_obj_p); } /* opfunc_create_implicit_class_constructor */ @@ -1064,8 +1072,8 @@ opfunc_set_class_attributes (ecma_object_t *obj_p, /**< object */ if (ECMA_PROPERTY_GET_TYPE (property) == ECMA_PROPERTY_TYPE_NAMEDDATA) { - JERRY_ASSERT (ecma_is_value_object (property_pair_p->values[index].value)); - if (ecma_is_property_enumerable (property)) + if (ecma_is_value_object (property_pair_p->values[index].value) + && ecma_is_property_enumerable (property)) { property_pair_p->header.types[index] = (uint8_t) (property & ~ECMA_PROPERTY_FLAG_ENUMERABLE); opfunc_set_home_object (ecma_get_object_from_value (property_pair_p->values[index].value), parent_env_p); diff --git a/tests/jerry/es2015/regression-test-issue-3606.js b/tests/jerry/es2015/regression-test-issue-3606.js index bcd1466eb..ce6e28d04 100644 --- a/tests/jerry/es2015/regression-test-issue-3606.js +++ b/tests/jerry/es2015/regression-test-issue-3606.js @@ -13,5 +13,5 @@ // limitations under the License. -var expected = '{"values":true,"keys":true,"findIndex":true,"find":true,"fill":true,"entries":true,"copyWithin":true}'; +var expected = '{"copyWithin":true,"entries":true,"fill":true,"find":true,"findIndex":true,"keys":true,"values":true}'; assert(JSON.stringify(Array.prototype[Symbol.unscopables]) === expected);