From 75385a604552e1e264fb9204cb3c343bea3dce47 Mon Sep 17 00:00:00 2001 From: Robert Fancsik Date: Mon, 28 Sep 2020 15:57:58 +0200 Subject: [PATCH] Improve arguments object (#4145) - Enhancement: Arguments object properties are now lazy instantiated - Bugfix: Mapped arguments object instantiated properties cannot be lcached - Bugfix: Mapped arguments should be constructed even if 0 formal parameters or arguments are provided - Update: remove 'caller' property of unmapped arguments object JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu --- jerry-core/ecma/base/ecma-gc.c | 95 +++- jerry-core/ecma/base/ecma-globals.h | 45 +- jerry-core/ecma/base/ecma-helpers.c | 34 +- jerry-core/ecma/base/ecma-helpers.h | 6 +- .../ecma/operations/ecma-arguments-object.c | 507 ++++++++++++++++++ ...ts-arguments.h => ecma-arguments-object.h} | 18 +- .../ecma/operations/ecma-function-object.c | 2 +- .../ecma/operations/ecma-objects-arguments.c | 358 ------------- jerry-core/ecma/operations/ecma-objects.c | 388 ++++++++------ tests/jerry/arguments.js | 1 - tests/jerry/es.next/arguments.js | 21 + tests/jerry/es5.1/arguments.js | 26 + tests/test262-es6-excludelist.xml | 15 +- tests/test262-esnext-excludelist.xml | 18 - 14 files changed, 943 insertions(+), 591 deletions(-) create mode 100644 jerry-core/ecma/operations/ecma-arguments-object.c rename jerry-core/ecma/operations/{ecma-objects-arguments.h => ecma-arguments-object.h} (62%) delete mode 100644 jerry-core/ecma/operations/ecma-objects-arguments.c create mode 100644 tests/jerry/es.next/arguments.js create mode 100644 tests/jerry/es5.1/arguments.js diff --git a/jerry-core/ecma/base/ecma-gc.c b/jerry-core/ecma/base/ecma-gc.c index 82c2111d7..16f7ca5df 100644 --- a/jerry-core/ecma/base/ecma-gc.c +++ b/jerry-core/ecma/base/ecma-gc.c @@ -149,6 +149,36 @@ ecma_deref_object (ecma_object_t *object_p) /**< object */ object_p->type_flags_refs = (uint16_t) (object_p->type_flags_refs - ECMA_OBJECT_REF_ONE); } /* ecma_deref_object */ +/** + * Mark objects referenced by arguments object + */ +static void +ecma_gc_mark_arguments_object (ecma_extended_object_t *ext_object_p) /**< arguments object */ +{ + JERRY_ASSERT (ecma_get_object_type ((ecma_object_t *) ext_object_p) == ECMA_OBJECT_TYPE_PSEUDO_ARRAY); + + ecma_unmapped_arguments_t *arguments_p = (ecma_unmapped_arguments_t *) ext_object_p; + ecma_value_t *argv_p = (ecma_value_t *) (arguments_p + 1); + + if (ext_object_p->u.pseudo_array.extra_info & ECMA_ARGUMENTS_OBJECT_MAPPED) + { + ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) ext_object_p; + argv_p = (ecma_value_t *) (mapped_arguments_p + 1); + + ecma_gc_set_object_visited (ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, mapped_arguments_p->lex_env)); + } + + uint32_t arguments_number = arguments_p->header.u.pseudo_array.u2.arguments_number; + + for (uint32_t i = 0; i < arguments_number; i++) + { + if (ecma_is_value_object (argv_p[i])) + { + ecma_gc_set_object_visited (ecma_get_object_from_value (argv_p[i])); + } + } +} /* ecma_gc_mark_arguments_object */ + /** * Mark referenced object from property */ @@ -706,10 +736,7 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */ { JERRY_ASSERT (ext_object_p->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS); - ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, - ext_object_p->u.pseudo_array.u2.lex_env_cp); - - ecma_gc_set_object_visited (lex_env_p); + ecma_gc_mark_arguments_object (ext_object_p); break; } } @@ -915,6 +942,49 @@ ecma_gc_free_native_pointer (ecma_property_t *property_p) /**< property */ } } /* ecma_gc_free_native_pointer */ +/** + * Free specified arguments object. + * + * @return allocated object's size + */ +static size_t +ecma_free_arguments_object (ecma_extended_object_t *ext_object_p) /**< arguments object */ +{ + JERRY_ASSERT (ecma_get_object_type ((ecma_object_t *) ext_object_p) == ECMA_OBJECT_TYPE_PSEUDO_ARRAY); + + size_t object_size = sizeof (ecma_unmapped_arguments_t); + + if (ext_object_p->u.pseudo_array.extra_info & ECMA_ARGUMENTS_OBJECT_MAPPED) + { + ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) ext_object_p; + object_size = sizeof (ecma_mapped_arguments_t); + +#if ENABLED (JERRY_SNAPSHOT_EXEC) + if (!(mapped_arguments_p->unmapped.header.u.pseudo_array.extra_info & ECMA_ARGUMENTS_OBJECT_STATIC_BYTECODE)) +#endif /* ENABLED (JERRY_SNAPSHOT_EXEC) */ + { + ecma_compiled_code_t *byte_code_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, + mapped_arguments_p->u.byte_code); + + ecma_bytecode_deref (byte_code_p); + } + } + + ecma_value_t *argv_p = (ecma_value_t *) (((uint8_t *) ext_object_p) + object_size); + ecma_unmapped_arguments_t *arguments_p = (ecma_unmapped_arguments_t *) ext_object_p; + uint32_t arguments_number = arguments_p->header.u.pseudo_array.u2.arguments_number; + + for (uint32_t i = 0; i < arguments_number; i++) + { + ecma_free_value_if_not_object (argv_p[i]); + } + + uint32_t saved_argument_count = JERRY_MAX (arguments_number, + arguments_p->header.u.pseudo_array.u1.formal_params_number); + + return object_size + (saved_argument_count * sizeof (ecma_value_t)); +} /* ecma_free_arguments_object */ + /** * Free specified fast access mode array object. */ @@ -1444,22 +1514,7 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */ { case ECMA_PSEUDO_ARRAY_ARGUMENTS: { - JERRY_ASSERT (ext_object_p->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS); - - uint32_t formal_params_number = ext_object_p->u.pseudo_array.u1.length; - ecma_value_t *arg_literal_p = (ecma_value_t *) (ext_object_p + 1); - - for (uint32_t i = 0; i < formal_params_number; i++) - { - if (arg_literal_p[i] != ECMA_VALUE_EMPTY) - { - ecma_string_t *name_p = ecma_get_string_from_value (arg_literal_p[i]); - ecma_deref_ecma_string (name_p); - } - } - - size_t formal_params_size = formal_params_number * sizeof (ecma_value_t); - ext_object_size += formal_params_size; + ext_object_size = ecma_free_arguments_object (ext_object_p); break; } #if ENABLED (JERRY_BUILTIN_TYPEDARRAY) diff --git a/jerry-core/ecma/base/ecma-globals.h b/jerry-core/ecma/base/ecma-globals.h index 001940089..0c8273217 100644 --- a/jerry-core/ecma/base/ecma-globals.h +++ b/jerry-core/ecma/base/ecma-globals.h @@ -215,6 +215,7 @@ enum * or function call argument list */ ECMA_VALUE_SYNC_ITERATOR = ECMA_MAKE_VALUE (12), /**< option for ecma_op_get_iterator: sync iterator is requested */ ECMA_VALUE_ASYNC_ITERATOR = ECMA_MAKE_VALUE (13), /**< option for ecma_op_get_iterator: async iterator is requested */ + ECMA_VALUE_INITIALIZED = ECMA_MAKE_VALUE (14), /**< represents initialized mapped arguments formal parameter */ }; #if !ENABLED (JERRY_NUMBER_TYPE_FLOAT64) @@ -648,7 +649,6 @@ typedef enum ECMA_PROPERTY_GET_NO_OPTIONS = 0, /**< no option flags for ecma_op_object_get_property */ ECMA_PROPERTY_GET_VALUE = 1u << 0, /**< fill virtual_value field for virtual properties */ ECMA_PROPERTY_GET_EXT_REFERENCE = 1u << 1, /**< get extended reference to the property */ - ECMA_PROPERTY_GET_HAS_OWN_PROP = 1u << 2, /**< internal [[HasOwnProperty]] method */ } ecma_property_get_option_bits_t; /** @@ -937,13 +937,13 @@ typedef struct * [[IterationKind]] property for %Iterator% */ union { - uint16_t length; /**< for arguments: length of names */ + uint16_t formal_params_number; /**< for arguments: formal parameters number */ uint16_t class_id; /**< for typedarray: the specific class name id */ uint16_t iterator_index; /**< for %Iterator%: [[%Iterator%NextIndex]] property */ } u1; union { - ecma_value_t lex_env_cp; /**< for arguments: lexical environment */ + uint32_t arguments_number; /**< for arguments: arguments number */ ecma_value_t arraybuffer; /**< for typedarray: internal arraybuffer */ ecma_value_t iterated_value; /**< for %Iterator%: [[IteratedObject]] property */ ecma_value_t spread_value; /**< for spread object: spreaded element */ @@ -2183,6 +2183,45 @@ typedef struct uint32_t lazy_string_named_props; /**< number of lazy instantiated properties */ } ecma_property_counter_t; +/** + * Arguments object related status flags + */ +typedef enum +{ + ECMA_ARGUMENTS_OBJECT_NO_FLAGS = 0, /* unmapped arguments object */ + 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_flags_t; + +/** + * Definition of unmapped arguments object + */ +typedef struct +{ + ecma_extended_object_t header; /**< object header */ + ecma_value_t callee; /**< 'callee' property */ +} ecma_unmapped_arguments_t; + +/** + * Definition of mapped arguments object + */ +typedef struct +{ + ecma_unmapped_arguments_t unmapped; /**< unmapped arguments object header */ + ecma_value_t lex_env; /**< environment reference */ + union + { + ecma_value_t byte_code; /**< callee's compiled code */ +#if ENABLED (JERRY_SNAPSHOT_EXEC) + ecma_compiled_code_t *byte_code_p; /**< real byte code pointer */ +#endif /* ENABLED (JERRY_SNAPSHOT_EXEC) */ + } u; +} ecma_mapped_arguments_t; + /** * @} * @} diff --git a/jerry-core/ecma/base/ecma-helpers.c b/jerry-core/ecma/base/ecma-helpers.c index 3f30ab366..f21fde176 100644 --- a/jerry-core/ecma/base/ecma-helpers.c +++ b/jerry-core/ecma/base/ecma-helpers.c @@ -1498,23 +1498,6 @@ ecma_bytecode_deref (ecma_compiled_code_t *bytecode_p) /**< byte code pointer */ ((size_t) bytecode_p->size) << JMEM_ALIGNMENT_LOG); } /* ecma_bytecode_deref */ -#if ENABLED (JERRY_ESNEXT) -/** - * Get the tagged template collection of the compiled code - * - * @return pointer to the tagged template collection - */ -ecma_collection_t * -ecma_compiled_code_get_tagged_template_collection (const ecma_compiled_code_t *bytecode_header_p) /**< compiled code */ -{ - JERRY_ASSERT (bytecode_header_p != NULL); - JERRY_ASSERT (bytecode_header_p->status_flags & CBC_CODE_FLAGS_HAS_TAGGED_LITERALS); - - ecma_value_t *base_p = ecma_compiled_code_resolve_function_name (bytecode_header_p); - - return ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, base_p[-1]); -} /* ecma_compiled_code_get_tagged_template_collection */ - /** * Get the number of formal parameters of the compiled code * @@ -1552,6 +1535,23 @@ ecma_compiled_code_resolve_arguments_start (const ecma_compiled_code_t *bytecode return ((ecma_value_t *) byte_p) - ecma_compiled_code_get_formal_params (bytecode_header_p); } /* ecma_compiled_code_resolve_arguments_start */ +#if ENABLED (JERRY_ESNEXT) +/** + * Get the tagged template collection of the compiled code + * + * @return pointer to the tagged template collection + */ +ecma_collection_t * +ecma_compiled_code_get_tagged_template_collection (const ecma_compiled_code_t *bytecode_header_p) /**< compiled code */ +{ + JERRY_ASSERT (bytecode_header_p != NULL); + JERRY_ASSERT (bytecode_header_p->status_flags & CBC_CODE_FLAGS_HAS_TAGGED_LITERALS); + + ecma_value_t *base_p = ecma_compiled_code_resolve_function_name (bytecode_header_p); + + return ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, base_p[-1]); +} /* ecma_compiled_code_get_tagged_template_collection */ + /** * Resolve the position of the function name of the compiled code * diff --git a/jerry-core/ecma/base/ecma-helpers.h b/jerry-core/ecma/base/ecma-helpers.h index 03a83ebd4..d86af40da 100644 --- a/jerry-core/ecma/base/ecma-helpers.h +++ b/jerry-core/ecma/base/ecma-helpers.h @@ -536,12 +536,10 @@ void ecma_raise_error_from_error_reference (ecma_value_t value); void ecma_bytecode_ref (ecma_compiled_code_t *bytecode_p); void ecma_bytecode_deref (ecma_compiled_code_t *bytecode_p); -#if ENABLED (JERRY_ESNEXT) -ecma_collection_t *ecma_compiled_code_get_tagged_template_collection (const ecma_compiled_code_t *bytecode_header_p); -#endif /* ENABLED (JERRY_ESNEXT) */ -#if ENABLED (JERRY_ESNEXT) uint32_t ecma_compiled_code_get_formal_params (const ecma_compiled_code_t *bytecode_p); ecma_value_t *ecma_compiled_code_resolve_arguments_start (const ecma_compiled_code_t *bytecode_header_p); +#if ENABLED (JERRY_ESNEXT) +ecma_collection_t *ecma_compiled_code_get_tagged_template_collection (const ecma_compiled_code_t *bytecode_header_p); ecma_value_t *ecma_compiled_code_resolve_function_name (const ecma_compiled_code_t *bytecode_header_p); #endif /* ENABLED (JERRY_ESNEXT) */ ecma_value_t ecma_get_resource_name (const ecma_compiled_code_t *bytecode_p); diff --git a/jerry-core/ecma/operations/ecma-arguments-object.c b/jerry-core/ecma/operations/ecma-arguments-object.c new file mode 100644 index 000000000..b92343703 --- /dev/null +++ b/jerry-core/ecma/operations/ecma-arguments-object.c @@ -0,0 +1,507 @@ +/* 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. + */ + +#include "ecma-alloc.h" +#include "ecma-builtin-helpers.h" +#include "ecma-builtins.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-helpers.h" +#include "ecma-lex-env.h" +#include "ecma-objects.h" +#include "ecma-arguments-object.h" +#include "ecma-objects-general.h" +#include "jrt.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaargumentsobject ECMA arguments object related routines + * @{ + */ + +/** + * Arguments object creation operation. + * + * See also: ECMA-262 v5, 10.6 + */ +void +ecma_op_create_arguments_object (ecma_object_t *func_obj_p, /**< callee function */ + ecma_object_t *lex_env_p, /**< lexical environment the Arguments + * object is created for */ + vm_frame_ctx_shared_args_t *shared_p) /**< shared context data */ +{ + const ecma_compiled_code_t *bytecode_data_p = shared_p->header.bytecode_header_p; + uint16_t formal_params_number; + + if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + formal_params_number = ((cbc_uint16_arguments_t *) bytecode_data_p)->argument_end; + } + else + { + formal_params_number = ((cbc_uint8_arguments_t *) bytecode_data_p)->argument_end; + } + + uint32_t object_size = sizeof (ecma_unmapped_arguments_t); + uint32_t saved_arg_count = JERRY_MAX (shared_p->arg_list_len, formal_params_number); + uint8_t flags = ECMA_ARGUMENTS_OBJECT_NO_FLAGS; + + if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED) + { + flags = ECMA_ARGUMENTS_OBJECT_MAPPED; + object_size = sizeof (ecma_mapped_arguments_t); + +#if ENABLED (JERRY_SNAPSHOT_EXEC) + if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION) + { + flags |= ECMA_ARGUMENTS_OBJECT_STATIC_BYTECODE; + } +#endif /* ENABLED (JERRY_SNAPSHOT_EXEC) */ + } + + ecma_object_t *obj_p = ecma_create_object (ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE), + object_size + (saved_arg_count * sizeof (ecma_value_t)), + ECMA_OBJECT_TYPE_PSEUDO_ARRAY); + + ecma_unmapped_arguments_t *arguments_p = (ecma_unmapped_arguments_t *) obj_p; + + arguments_p->header.u.pseudo_array.type = ECMA_PSEUDO_ARRAY_ARGUMENTS; + arguments_p->header.u.pseudo_array.extra_info = flags; + arguments_p->header.u.pseudo_array.u1.formal_params_number = formal_params_number; + arguments_p->header.u.pseudo_array.u2.arguments_number = 0; + arguments_p->callee = ecma_make_object_value (func_obj_p); + + ecma_value_t *argv_p = (ecma_value_t *) (((uint8_t *) obj_p) + object_size); + + for (uint32_t i = 0; i < shared_p->arg_list_len; i++) + { + argv_p[i] = ecma_copy_value_if_not_object (shared_p->arg_list_p[i]); + } + + for (uint32_t i = shared_p->arg_list_len; i < saved_arg_count; i++) + { + argv_p[i] = ECMA_VALUE_INITIALIZED; + } + + arguments_p->header.u.pseudo_array.u2.arguments_number = shared_p->arg_list_len; + + if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED) + { + ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) obj_p; + + ECMA_SET_INTERNAL_VALUE_POINTER (mapped_arguments_p->lex_env, lex_env_p); + +#if ENABLED (JERRY_SNAPSHOT_EXEC) + if (flags & ECMA_ARGUMENTS_OBJECT_STATIC_BYTECODE) + { + mapped_arguments_p->u.byte_code_p = (ecma_compiled_code_t *) bytecode_data_p; + } + else +#endif /* ENABLED (JERRY_SNAPSHOT_EXEC) */ + { + ECMA_SET_INTERNAL_VALUE_POINTER (mapped_arguments_p->u.byte_code, bytecode_data_p); + } + + ecma_bytecode_ref ((ecma_compiled_code_t *) bytecode_data_p); + + ecma_value_t *formal_parameter_start_p; + formal_parameter_start_p = ecma_compiled_code_resolve_arguments_start ((ecma_compiled_code_t *) bytecode_data_p); + + for (uint32_t i = 0; i < formal_params_number; i++) + { + /* For legacy (non-strict) argument definition the trailing duplicated arguments cannot be lazy instantiated + E.g: function f (a,a,a,a) {} */ + if (JERRY_UNLIKELY (ecma_is_value_empty (formal_parameter_start_p[i]))) + { + ecma_property_value_t *prop_value_p; + ecma_string_t *prop_name_p = ecma_new_ecma_string_from_uint32 (i); + + prop_value_p = ecma_create_named_data_property (obj_p, + prop_name_p, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, + NULL); + + ecma_deref_ecma_string (prop_name_p); + + prop_value_p->value = argv_p[i]; + argv_p[i] = ECMA_VALUE_EMPTY; + } + } + } + + uint8_t prop_flags = ((bytecode_data_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) ? ECMA_PROPERTY_FIXED + : ECMA_PROPERTY_FLAG_WRITABLE); + + ecma_property_value_t *prop_value_p; + prop_value_p = ecma_create_named_data_property (lex_env_p, + ecma_get_magic_string (LIT_MAGIC_STRING_ARGUMENTS), + prop_flags, + NULL); + + prop_value_p->value = ecma_make_object_value (obj_p); + ecma_deref_object (obj_p); +} /* ecma_op_create_arguments_object */ + +/** + * [[DefineOwnProperty]] 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_define_own_property (ecma_object_t *object_p, /**< the object */ + ecma_string_t *property_name_p, /**< property name */ + const ecma_property_descriptor_t *property_desc_p) /**< property + * descriptor */ +{ + /* 3. */ + ecma_value_t ret_value = ecma_op_general_object_define_own_property (object_p, + property_name_p, + property_desc_p); + + if (ECMA_IS_VALUE_ERROR (ret_value) + || !(((ecma_extended_object_t *) object_p)->u.pseudo_array.extra_info & ECMA_ARGUMENTS_OBJECT_MAPPED)) + { + return ret_value; + } + + ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) object_p; + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index >= mapped_arguments_p->unmapped.header.u.pseudo_array.u1.formal_params_number) + { + return ret_value; + } + + ecma_value_t *argv_p = (ecma_value_t *) (mapped_arguments_p + 1); + + if (!ecma_is_value_empty (argv_p[index])) + { + if (property_desc_p->flags & (ECMA_PROP_IS_GET_DEFINED | ECMA_PROP_IS_SET_DEFINED)) + { + ecma_free_value_if_not_object (argv_p[index]); + argv_p[index] = ECMA_VALUE_EMPTY; + } + else + { + if (property_desc_p->flags & ECMA_PROP_IS_VALUE_DEFINED) + { + 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); + + ecma_value_t completion = ecma_op_set_mutable_binding (lex_env_p, + name_p, + property_desc_p->value, + true); + + JERRY_ASSERT (ecma_is_value_empty (completion)); + } + + if ((property_desc_p->flags & ECMA_PROP_IS_WRITABLE_DEFINED) + && !(property_desc_p->flags & ECMA_PROP_IS_WRITABLE)) + { + ecma_free_value_if_not_object (argv_p[index]); + argv_p[index] = ECMA_VALUE_EMPTY; + } + } + } + + 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.pseudo_array.extra_info & 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.pseudo_array.u1.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 + * + * @return pointer property, if one was instantiated, + * NULL - otherwise. + */ +ecma_property_t * +ecma_op_arguments_object_try_to_lazy_instantiate_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *property_name_p) /**< property's name */ +{ + JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_PSEUDO_ARRAY); + JERRY_ASSERT (((ecma_extended_object_t *) object_p)->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS); + + 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; + uint32_t arguments_number = arguments_p->header.u.pseudo_array.u2.arguments_number; + uint8_t flags = arguments_p->header.u.pseudo_array.extra_info; + + if (flags & ECMA_ARGUMENTS_OBJECT_MAPPED) + { + argv_p = (ecma_value_t *) (((ecma_mapped_arguments_t *) object_p) + 1); + } + + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index != ECMA_STRING_NOT_ARRAY_INDEX) + { + if (index >= arguments_number + || ecma_is_value_empty (argv_p[index]) + || argv_p[index] == ECMA_VALUE_INITIALIZED) + { + return NULL; + } + + prop_value_p = ecma_create_named_data_property (object_p, + property_name_p, + ECMA_PROPERTY_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.pseudo_array.u1.formal_params_number) + { + argv_p[index] = ECMA_VALUE_INITIALIZED; + } + else + { + argv_p[index] = ECMA_VALUE_EMPTY; + } + + return prop_p; + } + + if (property_name_p == ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH) + && !(flags & ECMA_ARGUMENTS_OBJECT_LENGTH_INITIALIZED)) + { + arguments_p->header.u.pseudo_array.extra_info |= 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, + &prop_p); + + prop_value_p->value = ecma_make_uint32_value (arguments_number); + } + + if (property_name_p == ecma_get_magic_string (LIT_MAGIC_STRING_CALLEE) + && !(flags & ECMA_ARGUMENTS_OBJECT_CALLEE_INITIALIZED)) + { + arguments_p->header.u.pseudo_array.extra_info |= 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, + &prop_p); + + prop_value_p->value = arguments_p->callee; + } + else + { + ecma_object_t *thrower_p = ecma_builtin_get (ECMA_BUILTIN_ID_TYPE_ERROR_THROWER); + + prop_value_p = ecma_create_named_accessor_property (object_p, + ecma_get_magic_string (LIT_MAGIC_STRING_CALLEE), + thrower_p, + thrower_p, + ECMA_PROPERTY_FIXED, + &prop_p); + } + return prop_p; + } + +#if !ENABLED (JERRY_ESNEXT) + if (property_name_p == ecma_get_magic_string (LIT_MAGIC_STRING_CALLER) + && !(arguments_p->header.u.pseudo_array.extra_info & ECMA_ARGUMENTS_OBJECT_CALLER_INITIALIZED)) + { + if (arguments_p->header.u.pseudo_array.extra_info & ECMA_ARGUMENTS_OBJECT_MAPPED) + { + return NULL; + } + + arguments_p->header.u.pseudo_array.extra_info |= ECMA_ARGUMENTS_OBJECT_CALLER_INITIALIZED; + + ecma_object_t *thrower_p = ecma_builtin_get (ECMA_BUILTIN_ID_TYPE_ERROR_THROWER); + + prop_value_p = ecma_create_named_accessor_property (object_p, + ecma_get_magic_string (LIT_MAGIC_STRING_CALLER), + thrower_p, + thrower_p, + ECMA_PROPERTY_FIXED, + &prop_p); + return prop_p; + } +#else /* ENABLED (JERRY_ESNEXT) */ + ecma_string_t *symbol_p = ecma_op_get_global_symbol (LIT_GLOBAL_SYMBOL_ITERATOR); + + if (property_name_p == symbol_p + && !(flags & ECMA_ARGUMENTS_OBJECT_ITERATOR_INITIALIZED)) + { + arguments_p->header.u.pseudo_array.extra_info |= ECMA_ARGUMENTS_OBJECT_ITERATOR_INITIALIZED; + + prop_value_p = ecma_create_named_data_property (object_p, + symbol_p, + ECMA_PROPERTY_CONFIGURABLE_WRITABLE, + &prop_p); + + prop_value_p->value = ecma_op_object_get_by_magic_id (ecma_builtin_get (ECMA_BUILTIN_ID_INTRINSIC_OBJECT), + LIT_INTERNAL_MAGIC_STRING_ARRAY_PROTOTYPE_VALUES); + + JERRY_ASSERT (ecma_is_value_object (prop_value_p->value)); + ecma_deref_object (ecma_get_object_from_value (prop_value_p->value)); + } + + ecma_deref_ecma_string (symbol_p); +#endif /* !ENABLED (JERRY_ESNEXT) */ + + return prop_p; +} /* ecma_op_arguments_object_try_to_lazy_instantiate_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 */ +{ + JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_PSEUDO_ARRAY); + JERRY_ASSERT (((ecma_extended_object_t *) obj_p)->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_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.pseudo_array.u2.arguments_number; + uint8_t flags = arguments_p->header.u.pseudo_array.extra_info; + + if (flags & ECMA_ARGUMENTS_OBJECT_MAPPED) + { + argv_p = (ecma_value_t *) (((ecma_mapped_arguments_t *) obj_p) + 1); + } + + 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_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 !ENABLED (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++; + } +#else /* ENABLED (JERRY_ESNEXT) */ + if (!(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 /* !ENABLED (JERRY_ESNEXT) */ +} /* ecma_op_arguments_object_list_lazy_property_names */ + +/** + * Get the formal parameter name corresponding to the given property index + * + * @return pointer to the formal parameter name + */ +ecma_string_t * +ecma_op_arguments_object_get_formal_parameter (ecma_mapped_arguments_t *mapped_arguments_p, /**< mapped arguments + * object */ + uint32_t index) /**< formal parameter index */ +{ + JERRY_ASSERT (mapped_arguments_p->unmapped.header.u.pseudo_array.extra_info & ECMA_ARGUMENTS_OBJECT_MAPPED); + JERRY_ASSERT (index < mapped_arguments_p->unmapped.header.u.pseudo_array.u1.formal_params_number); + + ecma_compiled_code_t *byte_code_p; + +#if ENABLED (JERRY_SNAPSHOT_EXEC) + if (mapped_arguments_p->unmapped.header.u.pseudo_array.extra_info & ECMA_ARGUMENTS_OBJECT_STATIC_BYTECODE) + { + byte_code_p = mapped_arguments_p->u.byte_code_p; + } + else +#endif /* ENABLED (JERRY_SNAPSHOT_EXEC) */ + { + byte_code_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, mapped_arguments_p->u.byte_code); + } + + ecma_value_t *formal_param_names_p = ecma_compiled_code_resolve_arguments_start (byte_code_p); + + return ecma_get_string_from_value (formal_param_names_p[index]); +} /* ecma_op_arguments_object_get_formal_parameter */ + +/** + * @} + * @} + */ diff --git a/jerry-core/ecma/operations/ecma-objects-arguments.h b/jerry-core/ecma/operations/ecma-arguments-object.h similarity index 62% rename from jerry-core/ecma/operations/ecma-objects-arguments.h rename to jerry-core/ecma/operations/ecma-arguments-object.h index e08f2bb78..551715d49 100644 --- a/jerry-core/ecma/operations/ecma-objects-arguments.h +++ b/jerry-core/ecma/operations/ecma-arguments-object.h @@ -13,8 +13,8 @@ * limitations under the License. */ -#ifndef ECMA_OBJECTS_ARGUMENTS_H -#define ECMA_OBJECTS_ARGUMENTS_H +#ifndef ECMA_ARGUMENTS_OBJECT_H +#define ECMA_ARGUMENTS_OBJECT_H #include "ecma-globals.h" #include "ecma-helpers.h" @@ -30,4 +30,16 @@ 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); -#endif /* !ECMA_OBJECTS_ARGUMENTS_H */ +ecma_property_t * +ecma_op_arguments_object_try_to_lazy_instantiate_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); + +ecma_string_t * +ecma_op_arguments_object_get_formal_parameter (ecma_mapped_arguments_t *mapped_arguments_p, + uint32_t index); +#endif /* !ECMA_ARGUMENTS_OBJECT_H */ diff --git a/jerry-core/ecma/operations/ecma-function-object.c b/jerry-core/ecma/operations/ecma-function-object.c index 5bb4315f4..adb835812 100644 --- a/jerry-core/ecma/operations/ecma-function-object.c +++ b/jerry-core/ecma/operations/ecma-function-object.c @@ -25,7 +25,7 @@ #include "ecma-lex-env.h" #include "ecma-objects.h" #include "ecma-objects-general.h" -#include "ecma-objects-arguments.h" +#include "ecma-arguments-object.h" #include "ecma-proxy-object.h" #include "ecma-symbol-object.h" #include "jcontext.h" diff --git a/jerry-core/ecma/operations/ecma-objects-arguments.c b/jerry-core/ecma/operations/ecma-objects-arguments.c deleted file mode 100644 index 02a06f836..000000000 --- a/jerry-core/ecma/operations/ecma-objects-arguments.c +++ /dev/null @@ -1,358 +0,0 @@ -/* 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. - */ - -#include "ecma-alloc.h" -#include "ecma-builtin-helpers.h" -#include "ecma-builtins.h" -#include "ecma-function-object.h" -#include "ecma-gc.h" -#include "ecma-globals.h" -#include "ecma-helpers.h" -#include "ecma-lex-env.h" -#include "ecma-objects.h" -#include "ecma-objects-arguments.h" -#include "ecma-objects-general.h" - -#include "jrt.h" - -/** \addtogroup ecma ECMA - * @{ - * - * \addtogroup ecmafunctionobject ECMA Function object related routines - * @{ - */ - -/** - * Arguments object creation operation. - * - * See also: ECMA-262 v5, 10.6 - */ -void -ecma_op_create_arguments_object (ecma_object_t *func_obj_p, /**< callee function */ - ecma_object_t *lex_env_p, /**< lexical environment the Arguments - object is created for */ - vm_frame_ctx_shared_args_t *shared_p) /**< shared context dta */ -{ - const ecma_compiled_code_t *bytecode_data_p = shared_p->header.bytecode_header_p; - bool is_strict = (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) != 0; - - uint32_t formal_params_number; - - if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) - { - cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_data_p; - - formal_params_number = args_p->argument_end; - } - else - { - cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_data_p; - - formal_params_number = args_p->argument_end; - } - - ecma_object_t *prototype_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); - ecma_object_t *obj_p; - uint32_t arguments_number = shared_p->arg_list_len; - - if ((bytecode_data_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED) - && arguments_number > 0 - && formal_params_number > 0) - { - size_t formal_params_size = formal_params_number * sizeof (ecma_value_t); - - obj_p = ecma_create_object (prototype_p, - sizeof (ecma_extended_object_t) + formal_params_size, - ECMA_OBJECT_TYPE_PSEUDO_ARRAY); - - ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; - - ext_object_p->u.pseudo_array.type = ECMA_PSEUDO_ARRAY_ARGUMENTS; - - ECMA_SET_INTERNAL_VALUE_POINTER (ext_object_p->u.pseudo_array.u2.lex_env_cp, lex_env_p); - - ext_object_p->u.pseudo_array.u1.length = (uint16_t) formal_params_number; - - ecma_value_t *arg_literal_p = (ecma_value_t *) (ext_object_p + 1); - - uint8_t *byte_p = (uint8_t *) bytecode_data_p; - byte_p += ((size_t) bytecode_data_p->size) << JMEM_ALIGNMENT_LOG; - byte_p -= formal_params_size; - - memcpy (arg_literal_p, byte_p, formal_params_size); - - for (uint32_t i = 0; i < formal_params_number; i++) - { - if (arg_literal_p[i] != ECMA_VALUE_EMPTY) - { - ecma_string_t *name_p = ecma_get_string_from_value (arg_literal_p[i]); - ecma_ref_ecma_string (name_p); - } - } - } - else - { - obj_p = ecma_create_object (prototype_p, sizeof (ecma_extended_object_t), ECMA_OBJECT_TYPE_CLASS); - - ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; - ext_object_p->u.class_prop.class_id = LIT_MAGIC_STRING_ARGUMENTS_UL; - } - - ecma_property_value_t *prop_value_p; - - /* 11.a, 11.b */ - for (uint32_t index = 0; - index < arguments_number; - index++) - { - ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index); - - prop_value_p = ecma_create_named_data_property (obj_p, - index_string_p, - ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, - NULL); - - const ecma_value_t *arguments_list_p = shared_p->arg_list_p; - prop_value_p->value = ecma_copy_value_if_not_object (arguments_list_p[index]); - - ecma_deref_ecma_string (index_string_p); - } - - /* 7. */ - prop_value_p = ecma_create_named_data_property (obj_p, - ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH), - ECMA_PROPERTY_CONFIGURABLE_WRITABLE, - NULL); - - prop_value_p->value = ecma_make_uint32_value (arguments_number); - - ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); - -#if ENABLED (JERRY_ESNEXT) - /* ECMAScript v6, 9.4.4.6.7, 9.4.4.7.22 */ - ecma_string_t *symbol_p = ecma_op_get_global_symbol (LIT_GLOBAL_SYMBOL_ITERATOR); - - prop_value_p = ecma_create_named_data_property (obj_p, - symbol_p, - ECMA_PROPERTY_CONFIGURABLE_WRITABLE, - NULL); - ecma_deref_ecma_string (symbol_p); - prop_value_p->value = ecma_op_object_get_by_magic_id (ecma_builtin_get (ECMA_BUILTIN_ID_INTRINSIC_OBJECT), - LIT_INTERNAL_MAGIC_STRING_ARRAY_PROTOTYPE_VALUES); - - JERRY_ASSERT (ecma_is_value_object (prop_value_p->value)); - ecma_deref_object (ecma_get_object_from_value (prop_value_p->value)); -#endif /* ENABLED (JERRY_ESNEXT) */ - - /* 13. */ - if (!is_strict) - { - prop_value_p = ecma_create_named_data_property (obj_p, - ecma_get_magic_string (LIT_MAGIC_STRING_CALLEE), - ECMA_PROPERTY_CONFIGURABLE_WRITABLE, - NULL); - - prop_value_p->value = ecma_make_object_value (func_obj_p); - } - else - { - ecma_object_t *thrower_p = ecma_builtin_get (ECMA_BUILTIN_ID_TYPE_ERROR_THROWER); - - /* 14. */ - prop_desc = ecma_make_empty_property_descriptor (); - { - prop_desc.flags = (ECMA_PROP_IS_GET_DEFINED - | ECMA_PROP_IS_SET_DEFINED - | ECMA_PROP_IS_ENUMERABLE_DEFINED - | ECMA_PROP_IS_CONFIGURABLE_DEFINED); - } - prop_desc.set_p = thrower_p; - prop_desc.get_p = thrower_p; - - ecma_value_t completion = ecma_op_object_define_own_property (obj_p, - ecma_get_magic_string (LIT_MAGIC_STRING_CALLEE), - &prop_desc); - - JERRY_ASSERT (ecma_is_value_true (completion)); - - completion = ecma_op_object_define_own_property (obj_p, - ecma_get_magic_string (LIT_MAGIC_STRING_CALLER), - &prop_desc); - JERRY_ASSERT (ecma_is_value_true (completion)); - } - - ecma_string_t *arguments_string_p = ecma_get_magic_string (LIT_MAGIC_STRING_ARGUMENTS); - - if (is_strict) - { - ecma_op_create_immutable_binding (lex_env_p, - arguments_string_p, - ecma_make_object_value (obj_p)); - } - else - { - ecma_value_t completion = ecma_op_create_mutable_binding (lex_env_p, - arguments_string_p, - false); - JERRY_ASSERT (ecma_is_value_empty (completion)); - - completion = ecma_op_set_mutable_binding (lex_env_p, - arguments_string_p, - ecma_make_object_value (obj_p), - false); - - JERRY_ASSERT (ecma_is_value_empty (completion)); - } - - ecma_deref_object (obj_p); -} /* ecma_op_create_arguments_object */ - -/** - * [[DefineOwnProperty]] 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_define_own_property (ecma_object_t *object_p, /**< the object */ - ecma_string_t *property_name_p, /**< property name */ - const ecma_property_descriptor_t *property_desc_p) /**< property - * descriptor */ -{ - /* 3. */ - ecma_value_t ret_value = ecma_op_general_object_define_own_property (object_p, - property_name_p, - property_desc_p); - - if (ECMA_IS_VALUE_ERROR (ret_value)) - { - return ret_value; - } - - uint32_t index = ecma_string_get_array_index (property_name_p); - - if (index == ECMA_STRING_NOT_ARRAY_INDEX) - { - return ret_value; - } - - ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; - - if (index >= ext_object_p->u.pseudo_array.u1.length) - { - return ret_value; - } - - ecma_value_t *arg_literal_p = (ecma_value_t *) (ext_object_p + 1); - - if (arg_literal_p[index] == ECMA_VALUE_EMPTY) - { - return ret_value; - } - - ecma_string_t *name_p = ecma_get_string_from_value (arg_literal_p[index]); - - if (property_desc_p->flags & (ECMA_PROP_IS_GET_DEFINED | ECMA_PROP_IS_SET_DEFINED)) - { - ecma_deref_ecma_string (name_p); - arg_literal_p[index] = ECMA_VALUE_EMPTY; - } - else - { - if (property_desc_p->flags & ECMA_PROP_IS_VALUE_DEFINED) - { - /* emulating execution of function described by MakeArgSetter */ - ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, - ext_object_p->u.pseudo_array.u2.lex_env_cp); - - ecma_value_t completion = ecma_op_set_mutable_binding (lex_env_p, - name_p, - property_desc_p->value, - true); - - JERRY_ASSERT (ecma_is_value_empty (completion)); - } - - if ((property_desc_p->flags & ECMA_PROP_IS_WRITABLE_DEFINED) - && !(property_desc_p->flags & ECMA_PROP_IS_WRITABLE)) - { - ecma_deref_ecma_string (name_p); - arg_literal_p[index] = ECMA_VALUE_EMPTY; - } - } - - 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_ERROR (ret_value)) - { - return ret_value; - } - - JERRY_ASSERT (ecma_is_value_boolean (ret_value)); - - if (ecma_is_value_true (ret_value)) - { - uint32_t index = ecma_string_get_array_index (property_name_p); - - if (index != ECMA_STRING_NOT_ARRAY_INDEX) - { - ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; - - if (index < ext_object_p->u.pseudo_array.u1.length) - { - ecma_value_t *arg_literal_p = (ecma_value_t *) (ext_object_p + 1); - - if (arg_literal_p[index] != ECMA_VALUE_EMPTY) - { - ecma_string_t *name_p = ecma_get_string_from_value (arg_literal_p[index]); - ecma_deref_ecma_string (name_p); - arg_literal_p[index] = ECMA_VALUE_EMPTY; - } - } - } - - ret_value = ECMA_VALUE_TRUE; - } - - return ret_value; -} /* ecma_op_arguments_object_delete */ - -/** - * @} - * @} - */ diff --git a/jerry-core/ecma/operations/ecma-objects.c b/jerry-core/ecma/operations/ecma-objects.c index 0deb02105..44cda7cd9 100644 --- a/jerry-core/ecma/operations/ecma-objects.c +++ b/jerry-core/ecma/operations/ecma-objects.c @@ -22,8 +22,9 @@ #include "ecma-helpers.h" #include "ecma-function-object.h" #include "ecma-lex-env.h" +#include "ecma-lcache.h" #include "ecma-string-object.h" -#include "ecma-objects-arguments.h" +#include "ecma-arguments-object.h" #include "ecma-objects-general.h" #include "ecma-objects.h" #include "ecma-proxy-object.h" @@ -80,7 +81,6 @@ ecma_op_object_get_own_property (ecma_object_t *object_p, /**< the object */ #endif /* ENABLED (JERRY_BUILTIN_PROXY) */ JERRY_ASSERT (property_name_p != NULL); JERRY_ASSERT (options == ECMA_PROPERTY_GET_NO_OPTIONS - || options == ECMA_PROPERTY_GET_HAS_OWN_PROP || property_ref_p != NULL); ecma_object_type_t type = ecma_get_object_type (object_p); @@ -256,46 +256,67 @@ ecma_op_object_get_own_property (ecma_object_t *object_p, /**< the object */ property_p = ecma_builtin_try_to_instantiate_property (object_p, property_name_p); } } - else if (type == ECMA_OBJECT_TYPE_FUNCTION) + else { -#if !ENABLED (JERRY_ESNEXT) - if (ecma_string_is_length (property_name_p)) + switch (type) { - if (options & ECMA_PROPERTY_GET_VALUE) + case ECMA_OBJECT_TYPE_FUNCTION: { - /* Get length virtual property. */ - ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p; - const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p); - - uint32_t len; - if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) +#if !ENABLED (JERRY_ESNEXT) + if (ecma_string_is_length (property_name_p)) { - cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_data_p; - len = args_p->argument_end; - } - else - { - cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_data_p; - len = args_p->argument_end; - } + if (options & ECMA_PROPERTY_GET_VALUE) + { + /* Get length virtual property. */ + ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p; + const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p); - property_ref_p->virtual_value = ecma_make_uint32_value (len); + uint32_t len; + if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_data_p; + len = args_p->argument_end; + } + else + { + cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_data_p; + len = args_p->argument_end; + } + + property_ref_p->virtual_value = ecma_make_uint32_value (len); + } + + return ECMA_PROPERTY_TYPE_VIRTUAL; + } + #endif /* !ENABLED (JERRY_ESNEXT) */ + + /* Get prototype physical property. */ + property_p = ecma_op_function_try_to_lazy_instantiate_property (object_p, property_name_p); + break; + } + case ECMA_OBJECT_TYPE_NATIVE_FUNCTION: + { + property_p = ecma_op_external_function_try_to_lazy_instantiate_property (object_p, property_name_p); + break; + } + case ECMA_OBJECT_TYPE_BOUND_FUNCTION: + { + property_p = ecma_op_bound_function_try_to_lazy_instantiate_property (object_p, property_name_p); + break; + } + case ECMA_OBJECT_TYPE_PSEUDO_ARRAY: + { + if (((ecma_extended_object_t *) object_p)->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS) + { + property_p = ecma_op_arguments_object_try_to_lazy_instantiate_property (object_p, property_name_p); + } + break; + } + default: + { + break; } - - return ECMA_PROPERTY_TYPE_VIRTUAL; } -#endif /* !ENABLED (JERRY_ESNEXT) */ - - /* Get prototype physical property. */ - property_p = ecma_op_function_try_to_lazy_instantiate_property (object_p, property_name_p); - } - else if (type == ECMA_OBJECT_TYPE_NATIVE_FUNCTION) - { - property_p = ecma_op_external_function_try_to_lazy_instantiate_property (object_p, property_name_p); - } - else if (type == ECMA_OBJECT_TYPE_BOUND_FUNCTION) - { - property_p = ecma_op_bound_function_try_to_lazy_instantiate_property (object_p, property_name_p); } if (property_p == NULL) @@ -304,36 +325,47 @@ ecma_op_object_get_own_property (ecma_object_t *object_p, /**< the object */ } } else if (type == ECMA_OBJECT_TYPE_PSEUDO_ARRAY - && (options & ECMA_PROPERTY_GET_HAS_OWN_PROP)) + && ((ecma_extended_object_t *) object_p)->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS + && (((ecma_extended_object_t *) object_p)->u.pseudo_array.extra_info & ECMA_ARGUMENTS_OBJECT_MAPPED)) { ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; - if (ext_object_p->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS) + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index < ext_object_p->u.pseudo_array.u1.formal_params_number) { - uint32_t index = ecma_string_get_array_index (property_name_p); + ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) ext_object_p; - if (index != ECMA_STRING_NOT_ARRAY_INDEX - && index < ext_object_p->u.pseudo_array.u1.length) + ecma_value_t *argv_p = (ecma_value_t *) (mapped_arguments_p + 1); + + if (!ecma_is_value_empty (argv_p[index])) { - ecma_value_t *arg_Literal_p = (ecma_value_t *) (ext_object_p + 1); - - if (arg_Literal_p[index] != ECMA_VALUE_EMPTY) +#if ENABLED (JERRY_LCACHE) + /* Mapped arguments initialized properties MUST not be lcached */ + if (ecma_is_property_lcached (property_p)) { - ecma_string_t *arg_name_p = ecma_get_string_from_value (arg_Literal_p[index]); + jmem_cpointer_t prop_name_cp; - ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, - ext_object_p->u.pseudo_array.u2.lex_env_cp); - - JERRY_ASSERT (lex_env_p != NULL - && ecma_is_lexical_environment (lex_env_p)); - - ecma_value_t binding_value = ecma_op_get_binding_value (lex_env_p, arg_name_p, true); - - ecma_named_data_property_assign_value (object_p, - ECMA_PROPERTY_VALUE_PTR (property_p), - binding_value); - ecma_free_value (binding_value); + if (JERRY_UNLIKELY (ECMA_IS_DIRECT_STRING (property_name_p))) + { + prop_name_cp = (jmem_cpointer_t) ECMA_GET_DIRECT_STRING_VALUE (property_name_p); + } + else + { + ECMA_SET_NON_NULL_POINTER (prop_name_cp, property_name_p); + } + ecma_lcache_invalidate (object_p, prop_name_cp, property_p); } +#endif /* ENABLED (JERRY_LCACHE) */ + 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); + + ecma_value_t binding_value = ecma_op_get_binding_value (lex_env_p, name_p, true); + + ecma_named_data_property_assign_value (object_p, + ECMA_PROPERTY_VALUE_PTR (property_p), + binding_value); + ecma_free_value (binding_value); } } } @@ -480,26 +512,23 @@ ecma_op_object_find_own (ecma_value_t base_value, /**< base value */ { ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; - if (ext_object_p->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS) + if (ext_object_p->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS + && ext_object_p->u.pseudo_array.extra_info & ECMA_ARGUMENTS_OBJECT_MAPPED) { uint32_t index = ecma_string_get_array_index (property_name_p); - if (index != ECMA_STRING_NOT_ARRAY_INDEX - && index < ext_object_p->u.pseudo_array.u1.length) + if (index < ext_object_p->u.pseudo_array.u1.formal_params_number) { - ecma_value_t *arg_Literal_p = (ecma_value_t *) (ext_object_p + 1); + ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) ext_object_p; - if (arg_Literal_p[index] != ECMA_VALUE_EMPTY) + ecma_value_t *argv_p = (ecma_value_t *) (mapped_arguments_p + 1); + + if (!ecma_is_value_empty (argv_p[index])) { - ecma_string_t *arg_name_p = ecma_get_string_from_value (arg_Literal_p[index]); + 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); - ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, - ext_object_p->u.pseudo_array.u2.lex_env_cp); - - JERRY_ASSERT (lex_env_p != NULL - && ecma_is_lexical_environment (lex_env_p)); - - return ecma_op_get_binding_value (lex_env_p, arg_name_p, true); + return ecma_op_get_binding_value (lex_env_p, name_p, true); } } } @@ -572,41 +601,62 @@ ecma_op_object_find_own (ecma_value_t base_value, /**< base value */ property_p = ecma_builtin_try_to_instantiate_property (object_p, property_name_p); } } - else if (type == ECMA_OBJECT_TYPE_FUNCTION) + else { -#if !ENABLED (JERRY_ESNEXT) - if (ecma_string_is_length (property_name_p)) + switch (type) { - /* Get length virtual property. */ - ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p; - const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p); - - uint32_t len; - if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + case ECMA_OBJECT_TYPE_FUNCTION: { - cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_data_p; - len = args_p->argument_end; - } - else - { - cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_data_p; - len = args_p->argument_end; - } +#if !ENABLED (JERRY_ESNEXT) + if (ecma_string_is_length (property_name_p)) + { + /* Get length virtual property. */ + ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p; + const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p); - return ecma_make_uint32_value (len); - } + uint32_t len; + if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + { + cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_data_p; + len = args_p->argument_end; + } + else + { + cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_data_p; + len = args_p->argument_end; + } + + return ecma_make_uint32_value (len); + } #endif /* !ENABLED (JERRY_ESNEXT) */ - /* Get prototype physical property. */ - property_p = ecma_op_function_try_to_lazy_instantiate_property (object_p, property_name_p); - } - else if (type == ECMA_OBJECT_TYPE_NATIVE_FUNCTION) - { - property_p = ecma_op_external_function_try_to_lazy_instantiate_property (object_p, property_name_p); - } - else if (type == ECMA_OBJECT_TYPE_BOUND_FUNCTION) - { - property_p = ecma_op_bound_function_try_to_lazy_instantiate_property (object_p, property_name_p); + /* Get prototype physical property. */ + property_p = ecma_op_function_try_to_lazy_instantiate_property (object_p, property_name_p); + break; + } + case ECMA_OBJECT_TYPE_NATIVE_FUNCTION: + { + property_p = ecma_op_external_function_try_to_lazy_instantiate_property (object_p, property_name_p); + break; + } + case ECMA_OBJECT_TYPE_BOUND_FUNCTION: + { + property_p = ecma_op_bound_function_try_to_lazy_instantiate_property (object_p, property_name_p); + break; + } + case ECMA_OBJECT_TYPE_PSEUDO_ARRAY: + { + if (((ecma_extended_object_t *) object_p)->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS) + { + property_p = ecma_op_arguments_object_try_to_lazy_instantiate_property (object_p, property_name_p); + } + break; + } + default: + { + break; + } + } } if (property_p == NULL) @@ -1207,26 +1257,22 @@ ecma_op_object_put_with_receiver (ecma_object_t *object_p, /**< the object */ { ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; - if (ext_object_p->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS) + if (ext_object_p->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS + && (ext_object_p->u.pseudo_array.extra_info & ECMA_ARGUMENTS_OBJECT_MAPPED)) { uint32_t index = ecma_string_get_array_index (property_name_p); - if (index != ECMA_STRING_NOT_ARRAY_INDEX - && index < ext_object_p->u.pseudo_array.u1.length) + if (index < ext_object_p->u.pseudo_array.u1.formal_params_number) { - ecma_value_t *arg_Literal_p = (ecma_value_t *) (ext_object_p + 1); + ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) ext_object_p; - if (arg_Literal_p[index] != ECMA_VALUE_EMPTY) + ecma_value_t *argv_p = (ecma_value_t *) (mapped_arguments_p + 1); + + if (!ecma_is_value_empty (argv_p[index])) { - ecma_string_t *arg_name_p = ecma_get_string_from_value (arg_Literal_p[index]); - - ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, - ext_object_p->u.pseudo_array.u2.lex_env_cp); - - JERRY_ASSERT (lex_env_p != NULL - && ecma_is_lexical_environment (lex_env_p)); - - ecma_op_set_mutable_binding (lex_env_p, arg_name_p, value, true); + 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); + ecma_op_set_mutable_binding (lex_env_p, name_p, value, true); return ECMA_VALUE_TRUE; } } @@ -1282,27 +1328,6 @@ ecma_op_object_put_with_receiver (ecma_object_t *object_p, /**< the object */ if (property_p == NULL) { - if (type == ECMA_OBJECT_TYPE_CLASS) - { - ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; - - if (ext_object_p->u.class_prop.class_id == LIT_MAGIC_STRING_STRING_UL) - { - uint32_t index = ecma_string_get_array_index (property_name_p); - - if (index != ECMA_STRING_NOT_ARRAY_INDEX) - { - ecma_value_t prim_value_p = ext_object_p->u.class_prop.u.value; - ecma_string_t *prim_value_str_p = ecma_get_string_from_value (prim_value_p); - - if (index < ecma_string_get_length (prim_value_str_p)) - { - return ecma_reject (is_throw); - } - } - } - } - if (ecma_get_object_is_builtin (object_p)) { if (type == ECMA_OBJECT_TYPE_FUNCTION && ecma_builtin_function_is_routine (object_p)) @@ -1320,32 +1345,74 @@ ecma_op_object_put_with_receiver (ecma_object_t *object_p, /**< the object */ property_p = ecma_builtin_try_to_instantiate_property (object_p, property_name_p); } } - else if (type == ECMA_OBJECT_TYPE_FUNCTION) + else { -#if ENABLED (JERRY_ESNEXT) - /* Uninitialized 'length' property is non-writable (ECMA-262 v6, 19.2.4.1) */ - if ((ecma_string_is_length (property_name_p)) - && (!ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (((ecma_extended_object_t *) object_p)->u.function.scope_cp))) + switch (type) { - return ecma_reject (is_throw); - } -#else /* !ENABLED (JERRY_ESNEXT) */ - if (ecma_string_is_length (property_name_p)) - { - return ecma_reject (is_throw); - } -#endif /* ENABLED (JERRY_ESNEXT) */ + case ECMA_OBJECT_TYPE_CLASS: + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; - /* Get prototype physical property. */ - property_p = ecma_op_function_try_to_lazy_instantiate_property (object_p, property_name_p); - } - else if (type == ECMA_OBJECT_TYPE_NATIVE_FUNCTION) - { - property_p = ecma_op_external_function_try_to_lazy_instantiate_property (object_p, property_name_p); - } - else if (type == ECMA_OBJECT_TYPE_BOUND_FUNCTION) - { - property_p = ecma_op_bound_function_try_to_lazy_instantiate_property (object_p, property_name_p); + if (ext_object_p->u.class_prop.class_id == LIT_MAGIC_STRING_STRING_UL) + { + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index != ECMA_STRING_NOT_ARRAY_INDEX) + { + ecma_value_t prim_value_p = ext_object_p->u.class_prop.u.value; + ecma_string_t *prim_value_str_p = ecma_get_string_from_value (prim_value_p); + + if (index < ecma_string_get_length (prim_value_str_p)) + { + return ecma_reject (is_throw); + } + } + } + break; + } + case ECMA_OBJECT_TYPE_FUNCTION: + { + #if ENABLED (JERRY_ESNEXT) + /* Uninitialized 'length' property is non-writable (ECMA-262 v6, 19.2.4.1) */ + if ((ecma_string_is_length (property_name_p)) + && (!ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (((ecma_extended_object_t *) object_p)->u.function.scope_cp))) + { + return ecma_reject (is_throw); + } + #else /* !ENABLED (JERRY_ESNEXT) */ + if (ecma_string_is_length (property_name_p)) + { + return ecma_reject (is_throw); + } + #endif /* ENABLED (JERRY_ESNEXT) */ + + /* Get prototype physical property. */ + property_p = ecma_op_function_try_to_lazy_instantiate_property (object_p, property_name_p); + break; + } + case ECMA_OBJECT_TYPE_NATIVE_FUNCTION: + { + property_p = ecma_op_external_function_try_to_lazy_instantiate_property (object_p, property_name_p); + break; + } + case ECMA_OBJECT_TYPE_BOUND_FUNCTION: + { + property_p = ecma_op_bound_function_try_to_lazy_instantiate_property (object_p, property_name_p); + break; + } + case ECMA_OBJECT_TYPE_PSEUDO_ARRAY: + { + if (((ecma_extended_object_t *) object_p)->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS) + { + property_p = ecma_op_arguments_object_try_to_lazy_instantiate_property (object_p, property_name_p); + } + break; + } + default: + { + break; + } + } } } @@ -1440,7 +1507,8 @@ ecma_op_object_put_with_receiver (ecma_object_t *object_p, /**< the object */ { ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; - if (ext_object_p->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS) + if (ext_object_p->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS + && ext_object_p->u.pseudo_array.extra_info & ECMA_ARGUMENTS_OBJECT_MAPPED) { return ecma_builtin_helper_def_prop (object_p, property_name_p, @@ -2057,6 +2125,10 @@ ecma_object_list_lazy_property_names (ecma_object_t *obj_p, /**< object */ { case ECMA_OBJECT_TYPE_PSEUDO_ARRAY: { + if (((ecma_extended_object_t *) obj_p)->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_ARGUMENTS) + { + ecma_op_arguments_object_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p); + } #if ENABLED (JERRY_BUILTIN_TYPEDARRAY) if (ecma_object_is_typedarray (obj_p)) { @@ -3052,7 +3124,7 @@ ecma_op_ordinary_object_has_own_property (ecma_object_t *object_p, /**< the obje ecma_property_t property = ecma_op_object_get_own_property (object_p, property_name_p, NULL, - ECMA_PROPERTY_GET_HAS_OWN_PROP); + ECMA_PROPERTY_GET_NO_OPTIONS); return property != ECMA_PROPERTY_TYPE_NOT_FOUND && property != ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP; } /* ecma_op_ordinary_object_has_own_property */ diff --git a/tests/jerry/arguments.js b/tests/jerry/arguments.js index b1014d599..3f49fddfe 100644 --- a/tests/jerry/arguments.js +++ b/tests/jerry/arguments.js @@ -120,7 +120,6 @@ fn_expr = function (a, b, c) } } - check_type_error_for_property (arguments, 'caller'); check_type_error_for_property (arguments, 'callee'); } diff --git a/tests/jerry/es.next/arguments.js b/tests/jerry/es.next/arguments.js new file mode 100644 index 000000000..2186fb5e3 --- /dev/null +++ b/tests/jerry/es.next/arguments.js @@ -0,0 +1,21 @@ +// 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. + +function f(a, b, c) +{ + 'use strict'; + assert(!Object.hasOwnProperty(arguments,'caller')); +} + +f(1, 2, 3); diff --git a/tests/jerry/es5.1/arguments.js b/tests/jerry/es5.1/arguments.js new file mode 100644 index 000000000..b5781b330 --- /dev/null +++ b/tests/jerry/es5.1/arguments.js @@ -0,0 +1,26 @@ +// 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. + +function f(a, b, c) +{ + 'use strict'; + try { + arguments['caller']; + assert(false); + } catch (e) { + assert(e instanceof TypeError); + } +} + +f(1, 2, 3); diff --git a/tests/test262-es6-excludelist.xml b/tests/test262-es6-excludelist.xml index a1a0f25e0..7688ac9ce 100644 --- a/tests/test262-es6-excludelist.xml +++ b/tests/test262-es6-excludelist.xml @@ -243,14 +243,6 @@ - - - - - - - - No longer a SyntaxError in ES11 @@ -344,4 +336,11 @@ RegExp accessors should no longer throw when called on the RegExp prototype RegExp accessors should no longer throw when called on the RegExp prototype RegExp accessors should no longer throw when called on the RegExp prototype + ES11: arguments object no longer has caller property + ES11: arguments object no longer has caller property + ES11: arguments object no longer has caller property + ES11: arguments object no longer has caller property + ES11: arguments object no longer has caller property + ES11: arguments object no longer has caller property + ES11: arguments object no longer has caller property diff --git a/tests/test262-esnext-excludelist.xml b/tests/test262-esnext-excludelist.xml index cac14f530..a8a9fcf89 100644 --- a/tests/test262-esnext-excludelist.xml +++ b/tests/test262-esnext-excludelist.xml @@ -1583,7 +1583,6 @@ - @@ -2867,23 +2866,6 @@ - - - - - - - - - - - - - - - - -