From 600967b04aefdb92272c6d32610b65b7a333883b Mon Sep 17 00:00:00 2001 From: Robert Fancsik Date: Thu, 6 Aug 2020 17:40:57 +0200 Subject: [PATCH] Improve arguments object - 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 | 378 +++++++------ 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, 938 insertions(+), 586 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 82c2111d7f..16f7ca5dfb 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 0019400894..0c8273217b 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 3f30ab3661..f21fde176b 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 03a83ebd4f..d86af40daa 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 0000000000..b923437037 --- /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 e08f2bb787..551715d497 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 5bb4315f4d..adb8358129 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 02a06f836c..0000000000 --- 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 0deb021059..44cda7cd92 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; + 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); + + 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; } - else + #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) { - cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_data_p; - len = args_p->argument_end; + property_p = ecma_op_arguments_object_try_to_lazy_instantiate_property (object_p, property_name_p); } - - property_ref_p->virtual_value = ecma_make_uint32_value (len); + 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 *arg_Literal_p = (ecma_value_t *) (ext_object_p + 1); + ecma_value_t *argv_p = (ecma_value_t *) (mapped_arguments_p + 1); - if (arg_Literal_p[index] != ECMA_VALUE_EMPTY) + if (!ecma_is_value_empty (argv_p[index])) + { +#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)); + 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, arg_name_p, true); + 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); - } + 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); - - if (arg_Literal_p[index] != ECMA_VALUE_EMPTY) - { - ecma_string_t *arg_name_p = ecma_get_string_from_value (arg_Literal_p[index]); + ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) ext_object_p; - 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 *argv_p = (ecma_value_t *) (mapped_arguments_p + 1); - JERRY_ASSERT (lex_env_p != NULL - && ecma_is_lexical_environment (lex_env_p)); + if (!ecma_is_value_empty (argv_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); - 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); + case ECMA_OBJECT_TYPE_FUNCTION: + { +#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); + + 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) */ - uint32_t len; - if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) + /* 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: { - cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_data_p; - len = args_p->argument_end; + property_p = ecma_op_external_function_try_to_lazy_instantiate_property (object_p, property_name_p); + break; } - else + case ECMA_OBJECT_TYPE_BOUND_FUNCTION: { - cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_data_p; - len = args_p->argument_end; + 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_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); } 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); - - if (arg_Literal_p[index] != ECMA_VALUE_EMPTY) - { - 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); + ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) ext_object_p; - JERRY_ASSERT (lex_env_p != NULL - && ecma_is_lexical_environment (lex_env_p)); + ecma_value_t *argv_p = (ecma_value_t *) (mapped_arguments_p + 1); - ecma_op_set_mutable_binding (lex_env_p, arg_name_p, value, true); + if (!ecma_is_value_empty (argv_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_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))) - { - return ecma_reject (is_throw); - } -#else /* !ENABLED (JERRY_ESNEXT) */ - if (ecma_string_is_length (property_name_p)) + switch (type) { - 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 b1014d5998..3f49fddfe9 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 0000000000..2186fb5e38 --- /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 0000000000..b5781b330c --- /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 cc9a56ad4d..a69ce80d83 100644 --- a/tests/test262-es6-excludelist.xml +++ b/tests/test262-es6-excludelist.xml @@ -243,14 +243,6 @@ - - - - - - - - No longer a SyntaxError in ES11 @@ -345,4 +337,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 894b3bb3bd..1502bf04db 100644 --- a/tests/test262-esnext-excludelist.xml +++ b/tests/test262-esnext-excludelist.xml @@ -1585,7 +1585,6 @@ - @@ -2872,23 +2871,6 @@ - - - - - - - - - - - - - - - - -