diff --git a/jerry-core/CMakeLists.txt b/jerry-core/CMakeLists.txt index f1ceee3b8a..b58bef01ff 100644 --- a/jerry-core/CMakeLists.txt +++ b/jerry-core/CMakeLists.txt @@ -272,7 +272,10 @@ set(SOURCE_CORE_FILES ecma/operations/ecma-bigint-object.c ecma/operations/ecma-bigint.c ecma/operations/ecma-boolean-object.c + ecma/operations/ecma-bound-function.c + ecma/operations/ecma-class-object.c ecma/operations/ecma-comparison.c + ecma/operations/ecma-constructor-function.c ecma/operations/ecma-container-object.c ecma/operations/ecma-conversion.c ecma/operations/ecma-dataview-object.c @@ -283,9 +286,11 @@ set(SOURCE_CORE_FILES ecma/operations/ecma-iterator-object.c ecma/operations/ecma-jobqueue.c ecma/operations/ecma-lex-env.c + ecma/operations/ecma-native-function.c ecma/operations/ecma-number-object.c ecma/operations/ecma-objects-general.c ecma/operations/ecma-objects.c + ecma/operations/ecma-ordinary-object.c ecma/operations/ecma-promise-object.c ecma/operations/ecma-proxy-object.c ecma/operations/ecma-reference.c @@ -451,7 +456,10 @@ if(ENABLE_AMALGAM) ecma/operations/ecma-bigint-object.h ecma/operations/ecma-bigint.h ecma/operations/ecma-boolean-object.h + ecma/operations/ecma-bound-function.h + ecma/operations/ecma-class-object.h ecma/operations/ecma-comparison.h + ecma/operations/ecma-constructor-function.h ecma/operations/ecma-container-object.h ecma/operations/ecma-conversion.h ecma/operations/ecma-dataview-object.h @@ -461,9 +469,11 @@ if(ENABLE_AMALGAM) ecma/operations/ecma-iterator-object.h ecma/operations/ecma-jobqueue.h ecma/operations/ecma-lex-env.h + ecma/operations/ecma-native-function.h ecma/operations/ecma-number-object.h ecma/operations/ecma-objects-general.h ecma/operations/ecma-objects.h + ecma/operations/ecma-ordinary-object.h ecma/operations/ecma-promise-object.h ecma/operations/ecma-proxy-object.h ecma/operations/ecma-reference.h diff --git a/jerry-core/api/jerryscript.c b/jerry-core/api/jerryscript.c index 97f527c4e3..b3ec0fc2d2 100644 --- a/jerry-core/api/jerryscript.c +++ b/jerry-core/api/jerryscript.c @@ -1450,15 +1450,14 @@ jerry_value_type (const jerry_value_t value) /**< input value to check */ * Used by jerry_object_type to get the type of class objects */ static const uint8_t jerry_class_object_type[] = { - /* These objects require custom property resolving. */ - JERRY_OBJECT_TYPE_STRING, /**< type of ECMA_OBJECT_CLASS_STRING */ - JERRY_OBJECT_TYPE_ARGUMENTS, /**< type of ECMA_OBJECT_CLASS_ARGUMENTS */ #if JERRY_BUILTIN_TYPEDARRAY JERRY_OBJECT_TYPE_TYPEDARRAY, /**< type of ECMA_OBJECT_CLASS_TYPEDARRAY */ #endif /* JERRY_BUILTIN_TYPEDARRAY */ #if JERRY_MODULE_SYSTEM JERRY_OBJECT_TYPE_MODULE_NAMESPACE, /**< type of ECMA_OBJECT_CLASS_MODULE_NAMESPACE */ #endif /* JERRY_MODULE_SYSTEM */ + JERRY_OBJECT_TYPE_STRING, /**< type of ECMA_OBJECT_CLASS_STRING */ + JERRY_OBJECT_TYPE_ARGUMENTS, /**< type of ECMA_OBJECT_CLASS_ARGUMENTS */ /* These objects are marked by Garbage Collector. */ #if JERRY_ESNEXT @@ -3192,7 +3191,7 @@ jerry_object_has (const jerry_value_t object, /**< object value */ ecma_object_t *obj_p = ecma_get_object_from_value (object); ecma_string_t *prop_name_p = ecma_get_prop_name_from_value (key); - return jerry_return (ecma_op_object_has_property (obj_p, prop_name_p)); + return jerry_return (ecma_internal_method_has_property (obj_p, prop_name_p)); } /* jerry_object_has */ /** @@ -3215,8 +3214,8 @@ jerry_object_has_own (const jerry_value_t object, /**< object value */ ecma_object_t *obj_p = ecma_get_object_from_value (object); ecma_string_t *prop_name_p = ecma_get_prop_name_from_value (key); - return jerry_return (ecma_op_object_has_own_property (obj_p, prop_name_p)); -} /* jerry_has_own_property */ + return ecma_op_object_has_own_property (obj_p, prop_name_p); +} /* jerry_object_has_own */ /** * Checks whether the object has the given internal property. @@ -3274,7 +3273,7 @@ jerry_object_delete (const jerry_value_t object, /**< object value */ return false; } - return ecma_op_object_delete (ecma_get_object_from_value (object), ecma_get_prop_name_from_value (key), false); + return ecma_internal_method_delete (ecma_get_object_from_value (object), ecma_get_prop_name_from_value (key), false); } /* jerry_object_delete */ /** @@ -3295,7 +3294,7 @@ jerry_object_delete_index (const jerry_value_t object, /**< object value */ } ecma_string_t *str_idx_p = ecma_new_ecma_string_from_uint32 (index); - ecma_value_t ret_value = ecma_op_object_delete (ecma_get_object_from_value (object), str_idx_p, false); + ecma_value_t ret_value = ecma_internal_method_delete (ecma_get_object_from_value (object), str_idx_p, false); ecma_deref_ecma_string (str_idx_p); return ret_value; @@ -3367,9 +3366,8 @@ jerry_object_get (const jerry_value_t object, /**< object value */ return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); } - jerry_value_t ret_value = - ecma_op_object_get (ecma_get_object_from_value (object), ecma_get_prop_name_from_value (key)); - return jerry_return (ret_value); + return jerry_return ( + ecma_internal_method_get (ecma_get_object_from_value (object), ecma_get_prop_name_from_value (key), object)); } /* jerry_object_get */ /** @@ -3440,16 +3438,21 @@ jerry_object_find_own (const jerry_value_t object, /**< object value */ } #endif /* JERRY_BUILTIN_PROXY */ - ecma_value_t ret_value = ecma_op_object_find_own (receiver, object_p, property_name_p); + ecma_property_descriptor_t prop_desc = ecma_internal_method_get_own_property (object_p, property_name_p); - if (ecma_is_value_found (ret_value)) + if (ecma_property_descriptor_error (&prop_desc)) + { + return jerry_return (ECMA_VALUE_ERROR); + } + + if (ecma_property_descriptor_found (&prop_desc)) { if (found_p != NULL) { *found_p = true; } - return jerry_return (ret_value); + return jerry_return (ecma_property_descriptor_get (&prop_desc, receiver)); } return ECMA_VALUE_UNDEFINED; @@ -3524,8 +3527,11 @@ jerry_object_set (const jerry_value_t object, /**< object value */ return jerry_throw_sz (JERRY_ERROR_TYPE, ecma_get_error_msg (ECMA_ERR_WRONG_ARGS_MSG)); } - return jerry_return ( - ecma_op_object_put (ecma_get_object_from_value (object), ecma_get_prop_name_from_value (key), value, true)); + return jerry_return (ecma_internal_method_set (ecma_get_object_from_value (object), + ecma_get_prop_name_from_value (key), + value, + object, + true)); } /* jerry_object_set */ /** @@ -3656,35 +3662,27 @@ jerry_property_descriptor (void) static jerry_property_descriptor_t jerry_property_descriptor_from_ecma (const ecma_property_descriptor_t *prop_desc_p) /**<[out] property_descriptor */ { + JERRY_ASSERT (!(prop_desc_p->flags & (ECMA_PROP_DESC_PROPERTY | ECMA_PROP_DESC_VIRTUAL))); + jerry_property_descriptor_t prop_desc = jerry_property_descriptor (); - prop_desc.flags = prop_desc_p->flags; + prop_desc.flags = (uint16_t) (prop_desc_p->flags & ECMA_PROP_DESC_FLAG_MASK); - if (prop_desc.flags & (JERRY_PROP_IS_VALUE_DEFINED)) + if (prop_desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED) { prop_desc.value = prop_desc_p->value; } if (prop_desc_p->flags & JERRY_PROP_IS_GET_DEFINED) { - prop_desc.getter = ECMA_VALUE_NULL; - - if (prop_desc_p->get_p != NULL) - { - prop_desc.getter = ecma_make_object_value (prop_desc_p->get_p); - JERRY_ASSERT (ecma_op_is_callable (prop_desc.getter)); - } + prop_desc.getter = + ecma_is_value_undefined (prop_desc_p->u.accessor.get) ? ECMA_VALUE_NULL : prop_desc_p->u.accessor.get; } if (prop_desc_p->flags & JERRY_PROP_IS_SET_DEFINED) { - prop_desc.setter = ECMA_VALUE_NULL; - - if (prop_desc_p->set_p != NULL) - { - prop_desc.setter = ecma_make_object_value (prop_desc_p->set_p); - JERRY_ASSERT (ecma_op_is_callable (prop_desc.setter)); - } + prop_desc.setter = + ecma_is_value_undefined (prop_desc_p->u.accessor.set) ? ECMA_VALUE_NULL : prop_desc_p->u.accessor.set; } return prop_desc; @@ -3702,7 +3700,7 @@ jerry_property_descriptor_from_ecma (const ecma_property_descriptor_t *prop_desc static ecma_property_descriptor_t jerry_property_descriptor_to_ecma (const jerry_property_descriptor_t *prop_desc_p) /**< input property_descriptor */ { - ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); + ecma_property_descriptor_t prop_desc = ecma_make_empty_define_property_descriptor (); prop_desc.flags = prop_desc_p->flags; @@ -3732,7 +3730,7 @@ jerry_property_descriptor_to_ecma (const jerry_property_descriptor_t *prop_desc_ if (ecma_op_is_callable (getter)) { - prop_desc.get_p = ecma_get_object_from_value (getter); + prop_desc.u.accessor.get = getter; } else if (!ecma_is_value_null (getter)) { @@ -3753,7 +3751,7 @@ jerry_property_descriptor_to_ecma (const jerry_property_descriptor_t *prop_desc_ if (ecma_op_is_callable (setter)) { - prop_desc.set_p = ecma_get_object_from_value (setter); + prop_desc.u.accessor.set = setter; } else if (!ecma_is_value_null (setter)) { @@ -3831,9 +3829,9 @@ jerry_object_define_own_prop (const jerry_value_t object, /**< object value */ return jerry_type_error_or_false (ECMA_ERR_WRONG_ARGS_MSG, prop_desc_p->flags); } - return jerry_return (ecma_op_object_define_own_property (ecma_get_object_from_value (object), - ecma_get_prop_name_from_value (key), - &prop_desc)); + return jerry_return (ecma_internal_method_define_own_property (ecma_get_object_from_value (object), + ecma_get_prop_name_from_value (key), + &prop_desc)); } /* jerry_object_define_own_prop */ /** @@ -3854,63 +3852,63 @@ jerry_object_get_own_prop (const jerry_value_t object, /**< object value */ return ECMA_VALUE_FALSE; } - ecma_property_descriptor_t prop_desc; - - ecma_value_t status = ecma_op_object_get_own_property_descriptor (ecma_get_object_from_value (object), - ecma_get_prop_name_from_value (key), - &prop_desc); + ecma_property_descriptor_t prop_desc = + ecma_internal_method_get_own_property (ecma_get_object_from_value (object), ecma_get_prop_name_from_value (key)); -#if JERRY_BUILTIN_PROXY - if (ECMA_IS_VALUE_ERROR (status)) + if (ecma_property_descriptor_error (&prop_desc)) { + ecma_free_property_descriptor (&prop_desc); return ecma_create_exception_from_context (); } -#endif /* JERRY_BUILTIN_PROXY */ - if (!ecma_is_value_true (status)) + if (!ecma_property_descriptor_found (&prop_desc)) { + ecma_free_property_descriptor (&prop_desc); return ECMA_VALUE_FALSE; } - /* The flags are always filled in the returned descriptor. */ - JERRY_ASSERT ( - (prop_desc.flags & JERRY_PROP_IS_CONFIGURABLE_DEFINED) && (prop_desc.flags & JERRY_PROP_IS_ENUMERABLE_DEFINED) - && ((prop_desc.flags & JERRY_PROP_IS_WRITABLE_DEFINED) || !(prop_desc.flags & JERRY_PROP_IS_VALUE_DEFINED))); - - prop_desc_p->flags = prop_desc.flags; + prop_desc_p->flags = (JERRY_PROP_IS_ENUMERABLE_DEFINED | JERRY_PROP_IS_CONFIGURABLE_DEFINED); prop_desc_p->value = ECMA_VALUE_UNDEFINED; prop_desc_p->getter = ECMA_VALUE_UNDEFINED; prop_desc_p->setter = ECMA_VALUE_UNDEFINED; - if (prop_desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED) + if (ecma_property_descriptor_is_data_descriptor (&prop_desc)) { - prop_desc_p->value = prop_desc.value; - } + prop_desc_p->flags |= (JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_WRITABLE_DEFINED); + prop_desc_p->value = ecma_copy_value (ecma_property_descriptor_value (&prop_desc)); - if (prop_desc_p->flags & JERRY_PROP_IS_GET_DEFINED) - { - if (prop_desc.get_p != NULL) - { - prop_desc_p->getter = ecma_make_object_value (prop_desc.get_p); - } - else + if (ecma_property_descriptor_is_writable (&prop_desc)) { - prop_desc_p->getter = ECMA_VALUE_NULL; + prop_desc_p->flags |= JERRY_PROP_IS_WRITABLE; } } - - if (prop_desc_p->flags & JERRY_PROP_IS_SET_DEFINED) + else { - if (prop_desc.set_p != NULL) + if (prop_desc.flags & JERRY_PROP_IS_GET_DEFINED) { - prop_desc_p->setter = ecma_make_object_value (prop_desc.set_p); + prop_desc_p->flags |= JERRY_PROP_IS_GET_DEFINED; + prop_desc_p->getter = ecma_copy_value (ecma_property_descriptor_accessor_getter_value (&prop_desc)); } - else + + if (prop_desc.flags & JERRY_PROP_IS_SET_DEFINED) { - prop_desc_p->setter = ECMA_VALUE_NULL; + prop_desc_p->flags |= JERRY_PROP_IS_SET_DEFINED; + prop_desc_p->getter = ecma_copy_value (ecma_property_descriptor_accessor_setter_value (&prop_desc)); } } + if (ecma_property_descriptor_is_configurable (&prop_desc)) + { + prop_desc_p->flags |= JERRY_PROP_IS_CONFIGURABLE; + } + + if (ecma_property_descriptor_is_enumerable (&prop_desc)) + { + prop_desc_p->flags |= JERRY_PROP_IS_ENUMERABLE; + } + + ecma_free_property_descriptor (&prop_desc); + return ECMA_VALUE_TRUE; } /* jerry_object_get_own_prop */ @@ -3966,7 +3964,7 @@ jerry_call (const jerry_value_t func_object, /**< function object to call */ } } - return jerry_return (ecma_op_function_validated_call (func_object, this_value, args_p, args_count)); + return jerry_return (ecma_internal_method_validated_call (func_object, this_value, args_p, args_count)); } /* jerry_call */ /** @@ -3999,10 +3997,10 @@ jerry_construct (const jerry_value_t func_object, /**< function object to call * } } - return jerry_return (ecma_op_function_construct (ecma_get_object_from_value (func_object), - ecma_get_object_from_value (func_object), - args_p, - args_count)); + return jerry_return (ecma_internal_method_construct (ecma_get_object_from_value (func_object), + ecma_get_object_from_value (func_object), + args_p, + args_count)); } /* jerry_construct */ /** @@ -4058,22 +4056,21 @@ jerry_object_proto (const jerry_value_t object) /**< object value */ ecma_object_t *obj_p = ecma_get_object_from_value (object); -#if JERRY_BUILTIN_PROXY - if (ECMA_OBJECT_IS_PROXY (obj_p)) - { - return jerry_return (ecma_proxy_object_get_prototype_of (obj_p)); - } -#endif /* JERRY_BUILTIN_PROXY */ + ecma_object_t *proto_p = ecma_internal_method_get_prototype_of (obj_p); - if (obj_p->u2.prototype_cp == JMEM_CP_NULL) + if (proto_p == NULL) { return ECMA_VALUE_NULL; } - ecma_object_t *proto_obj_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, obj_p->u2.prototype_cp); - ecma_ref_object (proto_obj_p); +#if JERRY_BUILTIN_PROXY + if (proto_p == ECMA_OBJECT_POINTER_ERROR) + { + return ECMA_VALUE_ERROR; + } +#endif /* JERRY_BUILTIN_PROXY */ - return ecma_make_object_value (proto_obj_p); + return ecma_make_object_value (proto_p); } /* jerry_object_proto */ /** @@ -4095,14 +4092,7 @@ jerry_object_set_proto (const jerry_value_t object, /**< object value */ } ecma_object_t *obj_p = ecma_get_object_from_value (object); -#if JERRY_BUILTIN_PROXY - if (ECMA_OBJECT_IS_PROXY (obj_p)) - { - return jerry_return (ecma_proxy_object_set_prototype_of (obj_p, proto)); - } -#endif /* JERRY_BUILTIN_PROXY */ - - return ecma_op_ordinary_object_set_prototype_of (obj_p, proto); + return jerry_return (ecma_internal_method_set_prototype_of (obj_p, proto)); } /* jerry_object_set_proto */ /** @@ -4449,9 +4439,13 @@ jerry_object_foreach (const jerry_value_t object, /**< object value */ { ecma_string_t *property_name_p = ecma_get_string_from_value (buffer_p[i]); - property_value = ecma_op_object_get (object_p, property_name_p); + property_value = ecma_internal_method_get (object_p, property_name_p, object); - if (ECMA_IS_VALUE_ERROR (property_value)) + if (!ecma_is_value_found (property_value)) + { + property_value = ECMA_VALUE_UNDEFINED; + } + else if (ECMA_IS_VALUE_ERROR (property_value)) { break; } @@ -4497,7 +4491,7 @@ jerry_object_property_names (const jerry_value_t object, /**< object */ while (true) { /* Step 1. Get Object.[[OwnKeys]] */ - ecma_collection_t *prop_names_p = ecma_op_object_own_property_keys (obj_iter_p, filter); + ecma_collection_t *prop_names_p = ecma_internal_method_own_property_keys (obj_iter_p, filter); #if JERRY_BUILTIN_PROXY if (prop_names_p == NULL) @@ -4545,26 +4539,27 @@ jerry_object_property_names (const jerry_value_t object, /**< object */ & (JERRY_PROPERTY_FILTER_EXCLUDE_NON_CONFIGURABLE | JERRY_PROPERTY_FILTER_EXCLUDE_NON_ENUMERABLE | JERRY_PROPERTY_FILTER_EXCLUDE_NON_WRITABLE)) { - ecma_property_descriptor_t prop_desc; - ecma_value_t status = ecma_op_object_get_own_property_descriptor (obj_iter_p, key_p, &prop_desc); + ecma_property_descriptor_t prop_desc = ecma_internal_method_get_own_property (obj_iter_p, key_p); -#if JERRY_BUILTIN_PROXY - if (ECMA_IS_VALUE_ERROR (status)) + if (ecma_property_descriptor_error (&prop_desc)) { ecma_collection_free (prop_names_p); ecma_collection_free (result_p); ecma_deref_object (obj_iter_p); + ecma_free_property_descriptor (&prop_desc); return ecma_create_exception_from_context (); } -#endif /* JERRY_BUILTIN_PROXY */ - JERRY_ASSERT (ecma_is_value_true (status)); - uint16_t flags = prop_desc.flags; + JERRY_ASSERT (ecma_property_descriptor_found (&prop_desc)); + bool is_configurable = ecma_property_descriptor_is_configurable (&prop_desc); + bool is_writable = ecma_property_descriptor_is_writable (&prop_desc); + bool is_enumerable = ecma_property_descriptor_is_enumerable (&prop_desc); + ecma_free_property_descriptor (&prop_desc); - if ((!(flags & JERRY_PROP_IS_CONFIGURABLE) && (filter & JERRY_PROPERTY_FILTER_EXCLUDE_NON_CONFIGURABLE)) - || (!(flags & JERRY_PROP_IS_ENUMERABLE) && (filter & JERRY_PROPERTY_FILTER_EXCLUDE_NON_ENUMERABLE)) - || (!(flags & JERRY_PROP_IS_WRITABLE) && (filter & JERRY_PROPERTY_FILTER_EXCLUDE_NON_WRITABLE))) + if ((!is_configurable && (filter & JERRY_PROPERTY_FILTER_EXCLUDE_NON_CONFIGURABLE)) + || (!is_enumerable && (filter & JERRY_PROPERTY_FILTER_EXCLUDE_NON_ENUMERABLE)) + || (!is_writable && (filter & JERRY_PROPERTY_FILTER_EXCLUDE_NON_WRITABLE))) { continue; } @@ -4622,7 +4617,7 @@ jerry_object_property_names (const jerry_value_t object, /**< object */ break; } - ecma_object_t *proto_p = ecma_op_object_get_prototype_of (obj_iter_p); + ecma_object_t *proto_p = ecma_internal_method_get_prototype_of (obj_iter_p); if (proto_p == NULL) { diff --git a/jerry-core/debugger/debugger.c b/jerry-core/debugger/debugger.c index d7c310c407..ba37c382dd 100644 --- a/jerry-core/debugger/debugger.c +++ b/jerry-core/debugger/debugger.c @@ -586,8 +586,9 @@ jerry_debugger_send_eval (const lit_utf8_byte_t *eval_string_p, /**< evaluated s if (ecma_is_value_object (result)) { - message = - ecma_op_object_find (ecma_get_object_from_value (result), ecma_get_magic_string (LIT_MAGIC_STRING_MESSAGE)); + message = ecma_op_object_find (ecma_get_object_from_value (result), + ecma_get_magic_string (LIT_MAGIC_STRING_MESSAGE), + result); if (!ecma_is_value_string (message) || ecma_string_is_empty (ecma_get_string_from_value (message))) { diff --git a/jerry-core/ecma/base/ecma-alloc.c b/jerry-core/ecma/base/ecma-alloc.c index 970b05ee80..447c0d1112 100644 --- a/jerry-core/ecma/base/ecma-alloc.c +++ b/jerry-core/ecma/base/ecma-alloc.c @@ -25,7 +25,6 @@ JERRY_STATIC_ASSERT (sizeof (ecma_property_value_t) == sizeof (ecma_value_t), size_of_ecma_property_value_t_must_be_equal_to_size_of_ecma_value_t); JERRY_STATIC_ASSERT (((sizeof (ecma_property_value_t) - 1) & sizeof (ecma_property_value_t)) == 0, size_of_ecma_property_value_t_must_be_power_of_2); - JERRY_STATIC_ASSERT (sizeof (ecma_extended_object_t) - sizeof (ecma_object_t) <= sizeof (uint64_t), size_of_ecma_extended_object_part_must_be_less_than_or_equal_to_8_bytes); diff --git a/jerry-core/ecma/base/ecma-error-messages.inc.h b/jerry-core/ecma/base/ecma-error-messages.inc.h index b131911a97..ad7247dab2 100644 --- a/jerry-core/ecma/base/ecma-error-messages.inc.h +++ b/jerry-core/ecma/base/ecma-error-messages.inc.h @@ -209,9 +209,6 @@ ECMA_ERROR_DEF (ECMA_ERR_MODULE_NOT_SUPPORTED, "Module support is disabled") #if JERRY_BUILTIN_TYPEDARRAY ECMA_ERROR_DEF (ECMA_ERR_OBJECT_IS_NOT_A_TYPEDARRAY, "Object is not a TypedArray") #endif /* JERRY_BUILTIN_TYPEDARRAY */ -#if JERRY_ESNEXT -ECMA_ERROR_DEF (ECMA_ERR_RECEIVER_MUST_BE_AN_OBJECT, "Receiver must be an object") -#endif /* JERRY_ESNEXT */ #if !(JERRY_ESNEXT) ECMA_ERROR_DEF (ECMA_ERR_SYMBOL_NOT_SUPPORTED, "Symbol support is disabled") #endif /* !(JERRY_ESNEXT) */ @@ -230,10 +227,9 @@ ECMA_ERROR_DEF (ECMA_ERR_INVALID_SPECIES_CONSTRUCTOR, "Invalid species construct #if !(JERRY_ESNEXT) ECMA_ERROR_DEF (ECMA_ERR_PROMISE_NOT_SUPPORTED, "Promise support is disabled") #endif /* !(JERRY_ESNEXT) */ -#if JERRY_BUILTIN_PROXY || JERRY_ESNEXT +#if JERRY_BUILTIN_PROXY ECMA_ERROR_DEF (ECMA_ERR_PROXY_TRAP_RETURNED_FALSISH, "Proxy trap returned falsish") -#endif /* JERRY_BUILTIN_PROXY \ -|| JERRY_ESNEXT */ +#endif /* JERRY_BUILTIN_PROXY */ #if JERRY_BUILTIN_REGEXP ECMA_ERROR_DEF (ECMA_ERR_MIN_GREATER_THAN_MAX, "Quantifier error: min > max") #endif /* JERRY_BUILTIN_REGEXP */ @@ -357,7 +353,6 @@ ECMA_ERROR_DEF (ECMA_ERR_COMPARE_FUNC_NOT_CALLABLE, "Compare function is not cal #if JERRY_BUILTIN_PROXY ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_PROXY_REQUIRES_NEW, "Constructor Proxy requires 'new'") #endif /* JERRY_BUILTIN_PROXY */ -ECMA_ERROR_DEF (ECMA_ERR_EXPECTED_A_CONFIGURABLE_PROPERTY, "Expected a configurable property") #if JERRY_ESNEXT ECMA_ERROR_DEF (ECMA_ERR_FIRST_PARAMETER_MUST_BE_CALLABLE, "First parameter must be callable") #endif /* JERRY_ESNEXT */ @@ -434,9 +429,10 @@ ECMA_ERROR_DEF (ECMA_ERR_MAXIMUM_TYPEDARRAY_SIZE_IS_REACHED, "Maximum TypedArray ECMA_ERROR_DEF (ECMA_ERR_THE_GIVEN_ARGUMENT_IS_NOT_A_SYMBOL, "The given argument is not a Symbol") ECMA_ERROR_DEF (ECMA_ERR_PARAMETER_REJECT_MUST_BE_CALLABLE, "'reject' parameter must be callable") #endif /* JERRY_ESNEXT */ -#if JERRY_BUILTIN_TYPEDARRAY || JERRY_ESNEXT +#if JERRY_BUILTIN_ATOMICS || JERRY_BUILTIN_TYPEDARRAY || JERRY_ESNEXT ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_TYPED_ARRAY, "Argument 'this' is not a TypedArray") -#endif /* JERRY_BUILTIN_TYPEDARRAY \ +#endif /* JERRY_BUILTIN_ATOMICS \ +|| JERRY_BUILTIN_TYPEDARRAY \ || JERRY_ESNEXT */ #if JERRY_SNAPSHOT_SAVE ECMA_ERROR_DEF (ECMA_ERR_CANNOT_ALLOCATE_MEMORY_LITERALS, "Cannot allocate memory for literals") @@ -547,11 +543,6 @@ ECMA_ERROR_DEF (ECMA_ERR_CONSTRUCTOR_UINT32_ARRAY_REQUIRES_NEW, "Constructor Uin #if JERRY_ESNEXT ECMA_ERROR_DEF (ECMA_ERR_GENERATOR_IS_CURRENTLY_UNDER_EXECUTION, "Generator is currently under execution") ECMA_ERROR_DEF (ECMA_ERR_ITERATOR_RETURN_RESULT_IS_NOT_OBJECT, "Iterator 'return' result is not object") -#endif /* JERRY_ESNEXT */ -#if JERRY_BUILTIN_TYPEDARRAY -ECMA_ERROR_DEF (ECMA_ERR_RETURNED_ARRAYBUFFER_HAS_BEEN_DETACHED, "Returned ArrayBuffer has been detached") -#endif /* JERRY_BUILTIN_TYPEDARRAY */ -#if JERRY_ESNEXT ECMA_ERROR_DEF (ECMA_ERR_SEARCH_STRING_CANNOT_BE_OF_TYPE_REGEXP, "Search string can't be of type: RegExp") ECMA_ERROR_DEF (ECMA_ERR_VALUE_RECEIVED_BY_YIELD_IS_NOT_OBJECT, "Value received by yield* is not object") #endif /* JERRY_ESNEXT */ @@ -730,9 +721,7 @@ ECMA_ERROR_DEF (ECMA_ERR_START_OFFSET_IS_OUTSIDE_THE_BOUNDS_OF_THE_BUFFER, #if JERRY_BUILTIN_SHAREDARRAYBUFFER ECMA_ERROR_DEF (ECMA_ERR_ARGUMENT_THIS_NOT_SHARED_ARRAY_BUFFER, "Argument 'this' is not a SharedArrayBuffer object") #endif /* JERRY_BUILTIN_SHAREDARRAYBUFFER */ -#if JERRY_ESNEXT ECMA_ERROR_DEF (ECMA_ERR_CLASS_CONSTRUCTOR_NEW, "Class constructor cannot be invoked without 'new'") -#endif /* JERRY_ESNEXT */ #if JERRY_BUILTIN_PROXY ECMA_ERROR_DEF (ECMA_ERR_INCORRECT_RETURN_PROXY_GET_TRAP, "Incorrect value is returned by a Proxy 'get' trap") ECMA_ERROR_DEF (ECMA_ERR_INCORRECT_RETURN_PROXY_SET_TRAP, "Incorrect value is returned by a Proxy 'set' trap") @@ -743,8 +732,6 @@ ECMA_ERROR_DEF (ECMA_ERR_CLASS_IS_NON_CONFIGURABLE, "Prototype property of a cla #if JERRY_BUILTIN_ARRAY && JERRY_ESNEXT ECMA_ERROR_DEF (ECMA_ERR_PUSHING_TOO_HIGH_ELEMENT, "Pushing element over 2**53-1 length is disallowed") #endif /* JERRY_BUILTIN_ARRAY && JERRY_ESNEXT */ -ECMA_ERROR_DEF (ECMA_ERR_THE_REQUESTED_PROPERTY_UPDATE_CANNOT_BE_PERFORMED, - "The requested property update cannot be performed") #if JERRY_BUILTIN_PROXY ECMA_ERROR_DEF (ECMA_ERR_TRAP_RESULT_NOT_INCLUDE_ALL_CONFIGURABLE_KEYS, "Trap result did not include all configurable keys") diff --git a/jerry-core/ecma/base/ecma-error-messages.ini b/jerry-core/ecma/base/ecma-error-messages.ini index d368ad9bb6..99e569bf3f 100644 --- a/jerry-core/ecma/base/ecma-error-messages.ini +++ b/jerry-core/ecma/base/ecma-error-messages.ini @@ -99,7 +99,6 @@ ECMA_ERR_DERIVED_ARRAY_BUFFER_CTOR_BUFFER_TOO_SMALL = "Derived ArrayBuffer const ECMA_ERR_DERIVED_CTOR_RETURN_NOR_OBJECT_OR_UNDEFINED = "Derived constructors may only return object or undefined" ECMA_ERR_INVALID_CODE_POINT_ERROR = "Error: Invalid code point" ECMA_ERR_EXPECTED_A_DATAVIEW_OBJECT = "Expected a DataView object" -ECMA_ERR_EXPECTED_A_CONFIGURABLE_PROPERTY = "Expected a configurable property" ECMA_ERR_EXPECTED_A_FUNCTION_OBJECT = "Expected a function object" ECMA_ERR_EXPECTED_AN_ARRAYBUFFER = "Expected an ArrayBuffer" ECMA_ERR_EXPECTED_AN_OBJECT = "Expected an object" @@ -213,7 +212,6 @@ ECMA_ERR_RESOLVE_MUST_BE_UNDEFINED = "Resolve must be undefined" ECMA_ERR_RESULT_OF_DEFAULTVALUE_IS_INVALID = "Result of [[DefaultValue]] is invalid" ECMA_ERR_RETURN_VALUE_IS_NOT_AN_ARRAYBUFFER_OBJECT = "Return value is not an ArrayBuffer object" ECMA_ERR_RETURN_VALUE_OF_EXEC_MUST_BE_AN_OBJECT_OR_NULL = "Return value of 'exec' must be an object or null" -ECMA_ERR_RETURNED_ARRAYBUFFER_HAS_BEEN_DETACHED = "Returned ArrayBuffer has been detached" ECMA_ERR_RIGHT_VALUE_OF_IN_MUST_BE_AN_OBJECT = "Right value of 'in' must be an object" ECMA_ERR_RIGHT_VALUE_OF_INSTANCEOF_MUST_BE_AN_OBJECT = "Right value of 'instanceof' must be an object" ECMA_ERR_SEARCH_STRING_CANNOT_BE_OF_TYPE_REGEXP = "Search string can't be of type: RegExp" @@ -234,7 +232,6 @@ ECMA_ERR_TARGET_NOT_EXTENSIBLE_DIFFERENT_PROTOTYPE_RETURNED = "Target object is ECMA_ERR_THE_MAPFN_ARGUMENT_IS_NOT_CALLABLE = "The 'mapfn' argument is not callable" ECMA_ERR_THE_GIVEN_ARGUMENT_IS_NOT_A_SYMBOL = "The given argument is not a Symbol" ECMA_ERR_TARGET_PROPERTY_CONFIGURE_ACCESSOR_WITHOUT_SETTER = "The property of a Proxy target is a non configurable accessor without a setter" -ECMA_ERR_THE_REQUESTED_PROPERTY_UPDATE_CANNOT_BE_PERFORMED = "The requested property update cannot be performed" ECMA_ERR_THE_STRUCTURE_IS_CYCLICAL = "The structure is cyclical" ECMA_ERR_THE_TWO_DESCRIPTORS_ARE_INCOMPATIBLE = "The two descriptors are incompatible" ECMA_ERR_TOO_MANY_ARGUMENTS_DECLARED_FOR_FUNCTION_APPLY = "Too many arguments declared for Function.apply" @@ -326,7 +323,6 @@ ECMA_ERR_PROXY_TARGET_IS_NOT_A_CONSTRUCTOR = "Proxy target is not a constructor" ECMA_ERR_MAXIMUM_CALL_STACK_SIZE_EXCEEDED = "Maximum call stack size exceeded" ECMA_ERR_INVALID_SNAPSHOT_FORMAT = "Invalid snapshot format" ECMA_ERR_INVALID_SNAPSHOT_VERSION_OR_FEATURES = "Invalid snapshot version or unsupported features present" -ECMA_ERR_RECEIVER_MUST_BE_AN_OBJECT = "Receiver must be an object" ECMA_ERR_CANNOT_DECLARE_SAME_PRIVATE_FIELD_TWICE = "Cannot declare same private field twice" ECMA_ERR_CANNOT_WRITE_PRIVATE_MEMBER_TO_AN_OBJECT_WHOSE_CLASS_DID_NOT_DECLARE_IT = "Cannot write private member to an object whose class did not declare it" ECMA_ERR_PRIVATE_METHOD_IS_NOT_WRITABLE = "Private method is not writable" diff --git a/jerry-core/ecma/base/ecma-globals.h b/jerry-core/ecma/base/ecma-globals.h index 91bb9c5402..872f64b9b0 100644 --- a/jerry-core/ecma/base/ecma-globals.h +++ b/jerry-core/ecma/base/ecma-globals.h @@ -387,18 +387,20 @@ typedef enum */ typedef enum { + /* These 4 bits must be kept in sync with jerry_property_descriptor_flags_t bits */ ECMA_PROPERTY_FLAG_CONFIGURABLE = (1u << 0), /**< property is configurable */ ECMA_PROPERTY_FLAG_ENUMERABLE = (1u << 1), /**< property is enumerable */ ECMA_PROPERTY_FLAG_WRITABLE = (1u << 2), /**< property is writable */ + ECMA_PROPERTY_FLAG_DATA = (1u << 3), /**< property contains data */ + ECMA_PROPERTY_FLAG_SINGLE_EXTERNAL = (1u << 2), /**< only one external pointer is assigned to this object */ - ECMA_PROPERTY_FLAG_DELETED = (1u << 3), /**< property is deleted */ - ECMA_PROPERTY_FLAG_BUILT_IN = (1u << 3), /**< property is defined by the ECMAScript standard */ - ECMA_FAST_ARRAY_FLAG = (1u << 3), /**< array is fast array */ - ECMA_PROPERTY_FLAG_LCACHED = (1u << 4), /**< property is lcached */ + ECMA_PROPERTY_FLAG_DELETED = (1u << 4), /**< property is deleted */ + ECMA_PROPERTY_FLAG_BUILT_IN = (1u << 4), /**< property is defined by the ECMAScript standard */ + ECMA_FAST_ARRAY_FLAG = (1u << 4), /**< array is fast array */ + ECMA_PROPERTY_FLAG_LCACHED = (1u << 5), /**< property is lcached */ #if JERRY_ESNEXT - ECMA_ARRAY_TEMPLATE_LITERAL = (1u << 4), /**< array is a template literal constructed by the parser */ + ECMA_ARRAY_TEMPLATE_LITERAL = (1u << 5), /**< array is a template literal constructed by the parser */ #endif /* JERRY_ESNEXT */ - ECMA_PROPERTY_FLAG_DATA = (1u << 5), /**< property contains data */ /* The last two bits contains an ECMA_DIRECT_STRING value. */ } ecma_property_flags_t; @@ -485,29 +487,6 @@ typedef enum #define ECMA_PROPERTY_TYPE_DELETED \ (ECMA_PROPERTY_FLAG_DELETED | (ECMA_DIRECT_STRING_SPECIAL << ECMA_PROPERTY_NAME_TYPE_SHIFT)) -/** - * Type of property not found. - */ -#define ECMA_PROPERTY_TYPE_NOT_FOUND ECMA_PROPERTY_TYPE_HASHMAP - -/** - * Type of property not found and no more searching in the proto chain. - */ -#define ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP ECMA_PROPERTY_TYPE_DELETED - -/** - * Type of property not found and an exception is thrown. - */ -#define ECMA_PROPERTY_TYPE_NOT_FOUND_AND_THROW \ - (ECMA_PROPERTY_FLAG_LCACHED | (ECMA_DIRECT_STRING_SPECIAL << ECMA_PROPERTY_NAME_TYPE_SHIFT)) - -/** - * Checks whether a property is not found. - */ -#define ECMA_PROPERTY_IS_FOUND(property) \ - (((property) & (ECMA_PROPERTY_FLAG_DATA | (ECMA_DIRECT_STRING_SPECIAL << ECMA_PROPERTY_NAME_TYPE_SHIFT))) \ - != (ECMA_DIRECT_STRING_SPECIAL << ECMA_PROPERTY_NAME_TYPE_SHIFT)) - /** * Abstract property representation. * @@ -602,7 +581,7 @@ typedef struct /** * Checks whether a property is internal property */ -#define ECMA_PROPERTY_IS_INTERNAL(property) ((property) >= ECMA_PROPERTY_INTERNAL) +#define ECMA_PROPERTY_IS_INTERNAL(property) (((property) &ECMA_PROPERTY_INTERNAL) >= ECMA_PROPERTY_INTERNAL) /** * Checks whether a property is raw data or accessor property @@ -613,7 +592,7 @@ typedef struct * Checks whether a property is raw data property (should only be used in assertions) */ #define ECMA_PROPERTY_IS_RAW_DATA(property) \ - (((property) &ECMA_PROPERTY_FLAG_DATA) && (property) < ECMA_PROPERTY_INTERNAL) + (((property) &ECMA_PROPERTY_FLAG_DATA) && !ECMA_PROPERTY_IS_INTERNAL (property)) /** * Create internal property. @@ -639,7 +618,7 @@ typedef struct * Returns true if the property is named property. */ #define ECMA_PROPERTY_IS_NAMED_PROPERTY(property) \ - ((property) < ECMA_PROPERTY_TYPE_HASHMAP || (property) >= ECMA_PROPERTY_INTERNAL) + ((property) < ECMA_PROPERTY_TYPE_HASHMAP || ECMA_PROPERTY_IS_INTERNAL (property)) /** * Add the offset part to a property for computing its property data pointer. @@ -660,57 +639,32 @@ typedef struct #define ECMA_PROPERTY_VALUE_PTR(property_p) ((ecma_property_value_t *) ECMA_PROPERTY_VALUE_DATA_PTR (property_p)) /** - * Property reference. It contains the value pointer - * for real, and the value itself for virtual properties. + * Internal object types. */ -typedef union +typedef enum { - ecma_property_value_t *value_p; /**< property value pointer for real properties */ - ecma_value_t virtual_value; /**< property value for virtual properties */ -} ecma_property_ref_t; + /* This 3 types must be in this order, see ECMA_OBJECT_GET_OWN_MAY_ABRUPT */ + ECMA_OBJECT_TYPE_CLASS, /**< Objects with class property */ + ECMA_OBJECT_TYPE_BUILT_IN_CLASS, /**< built-in object with class property */ + ECMA_OBJECT_TYPE_PROXY, /**< Proxy object ECMAScript v6 26.2 */ -/** - * Extended property reference, which also contains the - * property descriptor pointer for real properties. - */ -typedef struct -{ - ecma_property_ref_t property_ref; /**< property reference */ - ecma_property_t *property_p; /**< property descriptor pointer for real properties */ -} ecma_extended_property_ref_t; + /* This 5 types must be in this order, see ecma_op_object_is_callable */ + ECMA_OBJECT_TYPE_FUNCTION, /**< Function objects (15.3), created through 13.2 routine */ + ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION, /**< Native built-in function object */ + ECMA_OBJECT_TYPE_BOUND_FUNCTION, /**< Function objects (15.3), created through 15.3.4.5 routine */ + ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION, /**< implicit class constructor function */ + ECMA_OBJECT_TYPE_NATIVE_FUNCTION, /**< Native function object */ -/** - * Option flags for ecma_op_object_get_property. - */ -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_option_bits_t; + ECMA_OBJECT_TYPE_GENERAL, /**< all objects that are not belongs to the sub-types below */ + ECMA_OBJECT_TYPE_BUILT_IN_GENERAL, /**< built-in general object */ + ECMA_OBJECT_TYPE_ARRAY, /**< Array object (15.4) */ + ECMA_OBJECT_TYPE_BUILT_IN_ARRAY, /**< Built-in array object */ -/** - * Internal object types. - */ -typedef enum -{ - ECMA_OBJECT_TYPE_GENERAL = 0, /**< all objects that are not belongs to the sub-types below */ - ECMA_OBJECT_TYPE_BUILT_IN_GENERAL = 1, /**< built-in general object */ - ECMA_OBJECT_TYPE_CLASS = 2, /**< Objects with class property */ - ECMA_OBJECT_TYPE_BUILT_IN_CLASS = 3, /**< built-in object with class property */ - ECMA_OBJECT_TYPE_ARRAY = 4, /**< Array object (15.4) */ - ECMA_OBJECT_TYPE_BUILT_IN_ARRAY = 5, /**< Built-in array object */ - ECMA_OBJECT_TYPE_PROXY = 6, /**< Proxy object ECMAScript v6 26.2 */ - /* Note: these 4 types must be in this order. See IsCallable operation. */ - ECMA_OBJECT_TYPE_FUNCTION = 7, /**< Function objects (15.3), created through 13.2 routine */ - ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION = 8, /**< Native built-in function object */ - ECMA_OBJECT_TYPE_BOUND_FUNCTION = 9, /**< Function objects (15.3), created through 15.3.4.5 routine */ - ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION = 10, /**< implicit class constructor function */ - ECMA_OBJECT_TYPE_NATIVE_FUNCTION = 11, /**< Native function object */ - - ECMA_OBJECT_TYPE__MAX /**< maximum value */ + ECMA_OBJECT_TYPE__MAX, /**< maximum value */ } ecma_object_type_t; +#define ECMA_OBJECT_GET_OWN_MAY_ABRUPT(obj_p) (JERRY_UNLIKELY (ecma_get_object_type (obj_p) <= ECMA_OBJECT_TYPE_PROXY)) + /** * Base object types without built-in flag. * @@ -733,15 +687,15 @@ typedef enum */ typedef enum { - /* These objects require custom property resolving. */ - ECMA_OBJECT_CLASS_STRING, /**< String Object (ECMAScript v5.1, 4.3.18) */ - ECMA_OBJECT_CLASS_ARGUMENTS, /**< Arguments object (10.6) */ +/* These objects require custom property resolving. */ #if JERRY_BUILTIN_TYPEDARRAY ECMA_OBJECT_CLASS_TYPEDARRAY, /**< TypedArray which does NOT need extra space to store length and offset */ #endif /* JERRY_BUILTIN_TYPEDARRAY */ #if JERRY_MODULE_SYSTEM ECMA_OBJECT_CLASS_MODULE_NAMESPACE, /**< Module Namespace (ECMAScript v11, 9.4.6) */ #endif /* JERRY_MODULE_SYSTEM */ + ECMA_OBJECT_CLASS_STRING, /**< String Object (ECMAScript v5.1, 4.3.18) */ + ECMA_OBJECT_CLASS_ARGUMENTS, /**< Arguments object (10.6) */ /* These objects are marked by Garbage Collector. */ #if JERRY_ESNEXT @@ -1009,427 +963,326 @@ typedef ecma_value_t (*ecma_builtin_handler_t) (ecma_object_t *function_obj_p, #endif /* JERRY_BUILTIN_REALMS */ /** - * Builtin routine function object status flags + * Direct string types (2 bit). */ typedef enum { - ECMA_BUILTIN_ROUTINE_NO_OPTS = 0, /**< No options are provided */ - ECMA_BUILTIN_ROUTINE_LENGTH_INITIALIZED = (1u << 0), /**< 'length' property has been initialized */ - ECMA_BUILTIN_ROUTINE_NAME_INITIALIZED = (1u << 1), /**< 'name' property has been initialized */ - ECMA_BUILTIN_ROUTINE_GETTER = (1u << 2), /**< this routine is getter */ - ECMA_BUILTIN_ROUTINE_SETTER = (1u << 3), /**< this routine is setter */ -} ecma_builtin_routine_flags_t; + ECMA_DIRECT_STRING_PTR = 0, /**< string is a string pointer, only used by property names */ + ECMA_DIRECT_STRING_MAGIC = 1, /**< string is a magic string */ + ECMA_DIRECT_STRING_UINT = 2, /**< string is an unsigned int */ + ECMA_DIRECT_STRING_SPECIAL = 3, /**< string is special */ +} ecma_direct_string_type_t; /** - * Start position of bit set size in length_and_bitset_size field. + * Maximum value of the immediate part of a direct magic string. + * Must be compatible with the immediate property name. */ -#define ECMA_BUILT_IN_BITSET_SHIFT 5 +#if JERRY_CPOINTER_32_BIT +#define ECMA_DIRECT_STRING_MAX_IMM 0x07ffffff +#else /* !JERRY_CPOINTER_32_BIT */ +#define ECMA_DIRECT_STRING_MAX_IMM 0x0000ffff +#endif /* JERRY_CPOINTER_32_BIT */ /** - * Description of extended ECMA-object. - * - * The extended object is an object with extra fields. + * Shift for direct string value part in ecma_value_t. */ -typedef struct -{ - ecma_object_t object; /**< object header */ - - /** - * Description of extra fields. These extra fields depend on the object type. - */ - union - { - ecma_built_in_props_t built_in; /**< built-in object part */ - - /** - * Description of objects with class. - * - * Note: - * class is a reserved word in c++, so cls is used instead - */ - struct - { - uint8_t type; /**< class type of the object */ - /** - * Description of 8 bit extra fields. These extra fields depend on the type. - */ - union - { - uint8_t arguments_flags; /**< arguments object flags */ - uint8_t error_type; /**< jerry_error_t type of native error objects */ -#if JERRY_BUILTIN_DATE - uint8_t date_flags; /**< flags for date objects */ -#endif /* JERRY_BUILTIN_DATE */ -#if JERRY_MODULE_SYSTEM - uint8_t module_state; /**< Module state */ -#endif /* JERRY_MODULE_SYSTEM */ -#if JERRY_ESNEXT - uint8_t iterator_kind; /**< type of iterator */ - uint8_t regexp_string_iterator_flags; /**< flags for RegExp string iterator */ - uint8_t promise_flags; /**< Promise object flags */ -#endif /* JERRY_ESNEXT */ -#if JERRY_BUILTIN_CONTAINER - uint8_t container_flags; /**< container object flags */ -#endif /* JERRY_BUILTIN_CONTAINER */ -#if JERRY_BUILTIN_TYPEDARRAY - uint8_t array_buffer_flags; /**< ArrayBuffer flags */ - uint8_t typedarray_type; /**< type of typed array */ -#endif /* JERRY_BUILTIN_TYPEDARRAY */ - } u1; - /** - * Description of 16 bit extra fields. These extra fields depend on the type. - */ - union - { - uint16_t formal_params_number; /**< for arguments: formal parameters number */ -#if JERRY_MODULE_SYSTEM - uint16_t module_flags; /**< Module flags */ -#endif /* JERRY_MODULE_SYSTEM */ -#if JERRY_ESNEXT - uint16_t iterator_index; /**< for %Iterator%: [[%Iterator%NextIndex]] property */ - uint16_t executable_obj_flags; /**< executable object flags */ -#endif /* JERRY_ESNEXT */ -#if JERRY_BUILTIN_CONTAINER - uint16_t container_id; /**< magic string id of a container */ -#endif /* JERRY_BUILTIN_CONTAINER */ -#if JERRY_BUILTIN_TYPEDARRAY - uint16_t typedarray_flags; /**< typed array object flags */ -#endif /* JERRY_BUILTIN_TYPEDARRAY */ - } u2; - /** - * Description of 32 bit / value. These extra fields depend on the type. - */ - union - { - ecma_value_t value; /**< value of the object (e.g. boolean, number, string, etc.) */ -#if !JERRY_ESNEXT - ecma_value_t date; /**< Date object [[DateValue]] internal property */ -#endif /* !JERRY_ESNEXT */ - ecma_value_t target; /**< [[ProxyTarget]] or [[WeakRefTarget]] internal property */ -#if JERRY_BUILTIN_TYPEDARRAY - ecma_value_t arraybuffer; /**< for typedarray: ArrayBuffer reference */ -#endif /* JERRY_BUILTIN_TYPEDARRAY */ -#if JERRY_ESNEXT - ecma_value_t head; /**< points to the async generator task queue head item */ - ecma_value_t iterated_value; /**< for %Iterator%: [[IteratedObject]] property */ - ecma_value_t promise; /**< PromiseCapability[[Promise]] internal slot */ - ecma_value_t sync_iterator; /**< IteratorRecord [[Iterator]] internal slot for AsyncFromSyncIterator */ - ecma_value_t spread_value; /**< for spread object: spreaded element */ - int32_t tza; /**< TimeZone adjustment for date objects */ -#endif /* JERRY_ESNEXT */ - uint32_t length; /**< length related property (e.g. length of ArrayBuffer) */ - uint32_t arguments_number; /**< for arguments: arguments number */ -#if JERRY_MODULE_SYSTEM - uint32_t dfs_ancestor_index; /**< module dfs ancestor index (ES2020 15.2.1.16) */ -#endif /* JERRY_MODULE_SYSTEM */ - } u3; - } cls; - - /** - * Description of function objects. - */ - struct - { - jmem_cpointer_tag_t scope_cp; /**< function scope */ - ecma_value_t bytecode_cp; /**< function byte code */ - } function; - - /** - * Description of array objects. - */ - struct - { - uint32_t length; /**< length property value */ - uint32_t length_prop_and_hole_count; /**< length property attributes and number of array holes in - * a fast access mode array multiplied ECMA_FAST_ACCESS_HOLE_ONE */ - } array; - - /** - * Description of bound function object. - */ - struct - { - jmem_cpointer_tag_t target_function; /**< target function */ - ecma_value_t args_len_or_this; /**< length of arguments or this value */ - } bound_function; - -#if JERRY_ESNEXT - /** - * Description of implicit class constructor function. - */ - struct - { - ecma_value_t script_value; /**< script value */ - uint8_t flags; /**< constructor flags */ - } constructor_function; -#endif /* JERRY_ESNEXT */ - } u; -} ecma_extended_object_t; +#define ECMA_DIRECT_STRING_SHIFT (ECMA_VALUE_SHIFT + 2) /** - * Description of built-in extended ECMA-object. + * Full mask for direct strings. */ -typedef struct -{ - ecma_extended_object_t extended_object; /**< extended object part */ - ecma_built_in_props_t built_in; /**< built-in object part */ -} ecma_extended_built_in_object_t; +#define ECMA_DIRECT_STRING_MASK ((uintptr_t) (ECMA_DIRECT_TYPE_MASK | (0x3u << ECMA_VALUE_SHIFT))) /** - * Type of lexical environment with class + * Create an ecma direct string. */ -typedef enum -{ - ECMA_LEX_ENV_CLASS_TYPE_MODULE, /**< module object reference */ - ECMA_LEX_ENV_CLASS_TYPE_CLASS_ENV, /**< class constructor object reference */ -} ecma_lexical_environment_class_type_t; +#define ECMA_CREATE_DIRECT_STRING(type, value) \ + ((uintptr_t) (ECMA_TYPE_DIRECT_STRING | ((type) << ECMA_VALUE_SHIFT) | (value) << ECMA_DIRECT_STRING_SHIFT)) /** - * Description of lexical environment with class + * Create an ecma direct string from the given number. + * + * Note: the given number must be less or equal than ECMA_DIRECT_STRING_MAX_IMM */ -typedef struct -{ - ecma_object_t lexical_env; /**< lexical environment header */ - uint32_t type; /**< element of ecma_lexical_environment_class_type_t */ - ecma_object_t *object_p; /**< object reference */ -} ecma_lexical_environment_class_t; +#define ECMA_CREATE_DIRECT_UINT32_STRING(uint32_number) \ + ((ecma_string_t *) ECMA_CREATE_DIRECT_STRING (ECMA_DIRECT_STRING_UINT, (uintptr_t) uint32_number)) /** - * Check whether the given lexical class environment is a module + * Checks whether the string is direct. */ -#define ECMA_LEX_ENV_CLASS_IS_MODULE(lex_env_p) \ - (((lex_env_p)->type_flags_refs & ECMA_OBJECT_FLAG_LEXICAL_ENV_HAS_DATA) \ - && ((ecma_lexical_environment_class_t *) (lex_env_p))->type == ECMA_LEX_ENV_CLASS_TYPE_MODULE) +#define ECMA_IS_DIRECT_STRING(string_p) ((((uintptr_t) (string_p)) & 0x1) != 0) /** - * Description of native functions + * Checks whether the string is direct. */ -typedef struct -{ - ecma_extended_object_t extended_object; /**< extended object part */ -#if JERRY_BUILTIN_REALMS - ecma_value_t realm_value; /**< realm value */ -#endif /* JERRY_BUILTIN_REALMS */ - ecma_native_handler_t native_handler_cb; /**< external function */ -} ecma_native_function_t; +#define ECMA_IS_DIRECT_STRING_WITH_TYPE(string_p, type) \ + ((((uintptr_t) (string_p)) & ECMA_DIRECT_STRING_MASK) == ECMA_CREATE_DIRECT_STRING (type, 0)) /** - * Alignment for the fast access mode array length. - * The real length is aligned up for allocating the underlying buffer. + * Returns the type of a direct string. */ -#define ECMA_FAST_ARRAY_ALIGNMENT (8) +#define ECMA_GET_DIRECT_STRING_TYPE(string_p) ((((uintptr_t) (string_p)) >> ECMA_VALUE_SHIFT) & 0x3) /** - * Align the length of the fast mode array to get the allocated size of the underlying buffer + * Shift applied to type conversions. */ -#define ECMA_FAST_ARRAY_ALIGN_LENGTH(length) \ - (uint32_t) ((((length)) + ECMA_FAST_ARRAY_ALIGNMENT - 1) / ECMA_FAST_ARRAY_ALIGNMENT * ECMA_FAST_ARRAY_ALIGNMENT) +#define ECMA_STRING_TYPE_CONVERSION_SHIFT (ECMA_PROPERTY_NAME_TYPE_SHIFT - ECMA_VALUE_SHIFT) /** - * Compiled byte code data. + * Converts direct string type to property name type. */ -typedef struct -{ - uint16_t size; /**< real size >> JMEM_ALIGNMENT_LOG */ - uint16_t refs; /**< reference counter for the byte code */ - uint16_t status_flags; /**< various status flags: - * CBC_IS_FUNCTION check tells whether the byte code - * is function or regular expression. - * If function, the other flags must be CBC_CODE_FLAGS... - * If regexp, the other flags must be RE_FLAG... */ -} ecma_compiled_code_t; +#define ECMA_DIRECT_STRING_TYPE_TO_PROP_NAME_TYPE(string_p) \ + ((((uintptr_t) (string_p)) & (0x3 << ECMA_VALUE_SHIFT)) << ECMA_STRING_TYPE_CONVERSION_SHIFT) /** - * Description of bound function objects. + * Returns the value of a direct string. */ -typedef struct -{ - ecma_extended_object_t header; /**< extended object header */ -#if JERRY_ESNEXT - ecma_value_t target_length; /**< length of target function */ -#endif /* JERRY_ESNEXT */ -} ecma_bound_function_t; - -#if JERRY_SNAPSHOT_EXEC +#define ECMA_GET_DIRECT_STRING_VALUE(string_p) (((uintptr_t) (string_p)) >> ECMA_DIRECT_STRING_SHIFT) /** - * Description of static function objects. + * Maximum number of bytes that a long-utf8-string is able to store */ -typedef struct -{ - ecma_extended_object_t header; /**< header part */ - const ecma_compiled_code_t *bytecode_p; /**< real byte code pointer */ -} ecma_static_function_t; +#define ECMA_STRING_SIZE_LIMIT UINT32_MAX -#endif /* JERRY_SNAPSHOT_EXEC */ +typedef enum +{ + ECMA_STRING_CONTAINER_HEAP_UTF8_STRING, /**< actual data is on the heap as an utf-8 (cesu8) string + * maximum size is 2^16. */ + ECMA_STRING_CONTAINER_LONG_OR_EXTERNAL_STRING, /**< the string is a long string or provided externally + * and only its attributes are stored. */ + ECMA_STRING_CONTAINER_UINT32_IN_DESC, /**< string representation of an uint32 number */ + ECMA_STRING_CONTAINER_HEAP_ASCII_STRING, /**< actual data is on the heap as an ASCII string + * maximum size is 2^16. */ + ECMA_STRING_CONTAINER_MAGIC_STRING_EX, /**< the ecma-string is equal to one of external magic strings */ + ECMA_STRING_CONTAINER_SYMBOL, /**< the ecma-string is a symbol */ -#if JERRY_ESNEXT + ECMA_STRING_CONTAINER__MAX = ECMA_STRING_CONTAINER_SYMBOL /**< maximum value */ +} ecma_string_container_t; /** - * Description of arrow function objects. + * Mask for getting the container of a string. */ -typedef struct -{ - ecma_extended_object_t header; /**< extended object header */ - ecma_value_t this_binding; /**< value of 'this' binding */ - ecma_value_t new_target; /**< value of new.target */ -} ecma_arrow_function_t; - -#if JERRY_SNAPSHOT_EXEC +#define ECMA_STRING_CONTAINER_MASK 0x7u /** - * Description of static arrow function objects. + * Value for increasing or decreasing the reference counter. */ -typedef struct -{ - ecma_arrow_function_t header; - const ecma_compiled_code_t *bytecode_p; -} ecma_static_arrow_function_t; - -#endif /* JERRY_SNAPSHOT_EXEC */ - -#endif /* JERRY_ESNEXT */ +#define ECMA_STRING_REF_ONE (1u << 4) -#if JERRY_BUILTIN_CONTAINER /** - * Flags for container objects + * Maximum value of the reference counter (4294967280). */ -typedef enum -{ - ECMA_CONTAINER_FLAGS_EMPTY = (0), /** empty flags */ - ECMA_CONTAINER_FLAGS_WEAK = (1 << 0) /** container object is weak */ -} ecma_container_flags_t; +#define ECMA_STRING_MAX_REF (0xFFFFFFF0) /** - * Description of map collection. + * Flag that identifies that the string is static which means it is stored in JERRY_CONTEXT (string_list_cp) */ -typedef struct -{ - ecma_value_t key; /**< key value */ - ecma_value_t value; /**< value of the key */ -} ecma_container_pair_t; +#define ECMA_STATIC_STRING_FLAG (1 << 3) /** - * Size of a single element (in ecma_value_t unit). + * Set an ecma-string as static string */ -#define ECMA_CONTAINER_VALUE_SIZE 1 +#define ECMA_SET_STRING_AS_STATIC(string_p) (string_p)->refs_and_container |= ECMA_STATIC_STRING_FLAG /** - * Size of a key - value pair (in ecma_value_t unit). + * Checks whether the ecma-string is static string */ -#define ECMA_CONTAINER_PAIR_SIZE 2 +#define ECMA_STRING_IS_STATIC(string_p) ((string_p)->refs_and_container & ECMA_STATIC_STRING_FLAG) /** - * Size of the internal buffer. + * Returns with the container type of a string. */ -#define ECMA_CONTAINER_GET_SIZE(container_p) (container_p->buffer_p[0]) +#define ECMA_STRING_GET_CONTAINER(string_desc_p) \ + ((ecma_string_container_t) ((string_desc_p)->refs_and_container & ECMA_STRING_CONTAINER_MASK)) /** - * Remove the size field of the internal buffer. + * Checks whether the reference counter is 1 of a string. */ -#define ECMA_CONTAINER_SET_SIZE(container_p, size) (container_p->buffer_p[0] = (ecma_value_t) (size)) +#define ECMA_STRING_IS_REF_EQUALS_TO_ONE(string_desc_p) (((string_desc_p)->refs_and_container >> 4) == 1) /** - * Number of entries of the internal buffer. + * Checks whether the reference counter is 1 of an extended primitive. */ -#define ECMA_CONTAINER_ENTRY_COUNT(collection_p) (collection_p->item_count - 1) +#define ECMA_EXTENDED_PRIMITIVE_IS_REF_EQUALS_TO_ONE(extended_primitive_p) \ + (((extended_primitive_p)->refs_and_type >> 3) == 1) /** - * Pointer to the first entry of the internal buffer. + * ECMA string-value descriptor */ -#define ECMA_CONTAINER_START(collection_p) (collection_p->buffer_p + 1) +typedef struct +{ + /** Reference counter for the string */ + uint32_t refs_and_container; -#endif /* JERRY_BUILTIN_CONTAINER */ + /** + * Actual data or identifier of it's place in container (depending on 'container' field) + */ + union + { + lit_string_hash_t hash; /**< hash of the ASCII/UTF8 string */ + uint32_t magic_string_ex_id; /**< identifier of an external magic string (lit_magic_string_ex_id_t) */ + uint32_t uint32_number; /**< uint32-represented number placed locally in the descriptor */ + } u; +} ecma_string_t; /** - * Description of ECMA property descriptor - * - * See also: ECMA-262 v5, 8.10. - * - * Note: - * If a component of descriptor is undefined then corresponding - * field should contain it's default value. + * ECMA UTF8 string-value descriptor */ typedef struct { - uint16_t flags; /**< any combination of jerry_property_descriptor_flags_t bits */ - ecma_value_t value; /**< [[Value]] */ - ecma_object_t *get_p; /**< [[Get]] */ - ecma_object_t *set_p; /**< [[Set]] */ -} ecma_property_descriptor_t; + ecma_string_t header; /**< string header */ + uint16_t size; /**< size of this utf-8 string in bytes */ + uint16_t length; /**< length of this utf-8 string in characters */ +} ecma_short_string_t; /** - * Bitfield which represents a namedata property options in an ecma_property_descriptor_t - * Attributes: - * - is_get_defined, is_set_defined : false - * - is_configurable, is_writable, is_enumerable : undefined (false) - * - is_throw : undefined (false) - * - is_value_defined : true - * - is_configurable_defined, is_writable_defined, is_enumerable_defined : true + * Long or external CESU8 string-value descriptor */ -#define ECMA_NAME_DATA_PROPERTY_DESCRIPTOR_BITS \ - ((uint16_t) (JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_CONFIGURABLE_DEFINED | JERRY_PROP_IS_ENUMERABLE_DEFINED \ - | JERRY_PROP_IS_WRITABLE_DEFINED)) +typedef struct +{ + ecma_string_t header; /**< string header */ + const lit_utf8_byte_t *string_p; /**< string data */ + lit_utf8_size_t size; /**< size of this external string in bytes */ + lit_utf8_size_t length; /**< length of this external string in characters */ +} ecma_long_string_t; /** - * Bitmask to get a the physical property flags from an ecma_property_descriptor + * External UTF8 string-value descriptor */ -#define ECMA_PROPERTY_FLAGS_MASK \ - ((uint16_t) (JERRY_PROP_IS_CONFIGURABLE | JERRY_PROP_IS_ENUMERABLE | JERRY_PROP_IS_WRITABLE)) +typedef struct +{ + ecma_long_string_t header; /**< long string header */ + void *user_p; /**< user pointer passed to the callback when the string is freed */ +} ecma_external_string_t; /** - * Description of an ecma-number + * Header size of an ecma ASCII string */ -#if JERRY_NUMBER_TYPE_FLOAT64 -typedef double ecma_number_t; -#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ -typedef float ecma_number_t; -#endif /* !JERRY_NUMBER_TYPE_FLOAT64 */ +#define ECMA_ASCII_STRING_HEADER_SIZE ((lit_utf8_size_t) (sizeof (ecma_string_t) + sizeof (uint8_t))) /** - * Convert double to an ecma-number. + * Get the size of an ecma ASCII string */ -#define DOUBLE_TO_ECMA_NUMBER_T(value) ((ecma_number_t) (value)) +#define ECMA_ASCII_STRING_GET_SIZE(string_p) \ + ((lit_utf8_size_t) * ((lit_utf8_byte_t *) (string_p) + sizeof (ecma_string_t)) + 1) /** - * Value '0' of ecma_number_t + * Set the size of an ecma ASCII string */ -#define ECMA_NUMBER_ZERO ((ecma_number_t) 0.0f) +#define ECMA_ASCII_STRING_SET_SIZE(string_p, size) \ + (*((lit_utf8_byte_t *) (string_p) + sizeof (ecma_string_t)) = (uint8_t) ((size) -1)) /** - * Value '1' of ecma_number_t + * Get the start position of the string buffer of an ecma ASCII string */ -#define ECMA_NUMBER_ONE ((ecma_number_t) 1.0f) +#define ECMA_ASCII_STRING_GET_BUFFER(string_p) ((lit_utf8_byte_t *) (string_p) + ECMA_ASCII_STRING_HEADER_SIZE) /** - * Value '2' of ecma_number_t + * Get the start position of the string buffer of an ecma UTF8 string */ -#define ECMA_NUMBER_TWO ((ecma_number_t) 2.0f) +#define ECMA_SHORT_STRING_GET_BUFFER(string_p) ((lit_utf8_byte_t *) (string_p) + sizeof (ecma_short_string_t)) /** - * Value '0.5' of ecma_number_t + * Get the start position of the string buffer of an ecma long CESU8 string */ -#define ECMA_NUMBER_HALF ((ecma_number_t) 0.5f) +#define ECMA_LONG_STRING_BUFFER_START(string_p) ((lit_utf8_byte_t *) (string_p) + sizeof (ecma_long_string_t)) /** - * Value '-1' of ecma_number_t + * ECMA extended string-value descriptor */ -#define ECMA_NUMBER_MINUS_ONE ((ecma_number_t) -1.0f) +typedef struct +{ + ecma_string_t header; /**< string header */ + + union + { + ecma_value_t symbol_descriptor; /**< symbol descriptor string-value */ + ecma_value_t value; /**< original key value corresponds to the map key string */ + } u; +} ecma_extended_string_t; /** - * Maximum number of characters in string representation of ecma-number + * Description of ECMA property descriptor + * + * See also: ECMA-262 v5, 8.10. + * + * Note: + * If a component of descriptor is undefined then corresponding + * field should contain it's default value. */ -#define ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER 64 +typedef struct +{ + union + { + struct + { + ecma_value_t get; /**< [[Get]] */ + ecma_value_t set; /**< [[Set]] */ + } accessor; + ecma_property_t *property_p; + } u; + uint32_t flags; /**< any combination of jerry_property_descriptor_flags_t and bits */ + ecma_value_t value; /**< [[Value]] */ +} ecma_property_descriptor_t; + +#define ECMA_PROP_DESC_FLAG_OFFSET 16 +#define ECMA_PROP_DESC_FLAG_MASK ((1 << ECMA_PROP_DESC_FLAG_OFFSET) - 1) /** - * Maximum number of characters in string representation of ecma-uint32 + * Flags to describe the property reference */ -#define ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32 10 +typedef enum +{ + /* first 16 bits are reserved for jerry_property_descriptor_flags_t bits */ + ECMA_PROP_DESC_CONFIGURABLE = JERRY_PROP_IS_CONFIGURABLE | JERRY_PROP_IS_CONFIGURABLE_DEFINED, + ECMA_PROP_DESC_ENUMERABLE = JERRY_PROP_IS_ENUMERABLE | JERRY_PROP_IS_ENUMERABLE_DEFINED, + ECMA_PROP_DESC_WRITABLE = JERRY_PROP_IS_WRITABLE | JERRY_PROP_IS_WRITABLE_DEFINED, + ECMA_PROP_DESC_DATA = JERRY_PROP_IS_VALUE_DEFINED, + ECMA_PROP_DESC_ACCESSOR = (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED), + + ECMA_PROP_DESC_PROPERTY = 1 << ECMA_PROP_DESC_FLAG_OFFSET, /**< general property descriptor */ + ECMA_PROP_DESC_VIRTUAL = 1 << (ECMA_PROP_DESC_FLAG_OFFSET + 1), /**< property reference to a virtual property */ + ECMA_PROP_DESC_FOUND = 1 << (ECMA_PROP_DESC_FLAG_OFFSET + 2), /**< property reference found */ + ECMA_PROP_DESC_ERROR = 1 << (ECMA_PROP_DESC_FLAG_OFFSET + 3), /**< property reference search resulted in error */ + ECMA_PROP_DESC_VIRTUAL_NOT_FOUND_AND_STOP = 1 << (ECMA_PROP_DESC_FLAG_OFFSET + 4), /**< */ + + ECMA_PROP_DESC_PROPERTY_FOUND = ECMA_PROP_DESC_PROPERTY | ECMA_PROP_DESC_FOUND, + ECMA_PROP_DESC_VIRTUAL_FOUND = ECMA_PROP_DESC_VIRTUAL | ECMA_PROP_DESC_FOUND | ECMA_PROP_DESC_DATA, + + ECMA_PROP_DESC_DATA_CONFIGURABLE = ECMA_PROP_DESC_DATA | ECMA_PROP_DESC_CONFIGURABLE, + ECMA_PROP_DESC_DATA_ENUMERABLE = ECMA_PROP_DESC_DATA | ECMA_PROP_DESC_ENUMERABLE, + ECMA_PROP_DESC_DATA_WRITABLE = ECMA_PROP_DESC_DATA | ECMA_PROP_DESC_WRITABLE, + + ECMA_PROP_DESC_DATA_ENUMERABLE_WRITABLE = ECMA_PROP_DESC_DATA_ENUMERABLE | ECMA_PROP_DESC_DATA_WRITABLE, + ECMA_PROP_DESC_DATA_CONFIGURABLE_ENUMERABLE = ECMA_PROP_DESC_DATA_CONFIGURABLE | ECMA_PROP_DESC_DATA_ENUMERABLE, + ECMA_PROP_DESC_DATA_CONFIGURABLE_WRITABLE = ECMA_PROP_DESC_DATA_CONFIGURABLE | ECMA_PROP_DESC_DATA_WRITABLE, + + ECMA_PROP_DESC_DATA_CONFIGURABLE_ENUMERABLE_WRITABLE = + ECMA_PROP_DESC_DATA_CONFIGURABLE_ENUMERABLE | ECMA_PROP_DESC_DATA_WRITABLE, +} ecma_property_descriptor_flags_t; /** - * String is not a valid array index. + * Bitmask to get a the physical property flags from an ecma_property_descriptor */ -#define ECMA_STRING_NOT_ARRAY_INDEX UINT32_MAX +#define ECMA_PROPERTY_DESCRIPTOR_FLAGS_MASK \ + (JERRY_PROP_IS_CONFIGURABLE | JERRY_PROP_IS_ENUMERABLE | JERRY_PROP_IS_WRITABLE | ECMA_PROP_DESC_DATA) + +#define ECMA_PROPERTY_TO_PROPERTY_DESCRIPTOR_FLAGS(prop_p) \ + (uint32_t) ((JERRY_PROP_IS_CONFIGURABLE_DEFINED | JERRY_PROP_IS_ENUMERABLE_DEFINED | JERRY_PROP_IS_WRITABLE_DEFINED) \ + | ((*prop_p) & ECMA_PROPERTY_DESCRIPTOR_FLAGS_MASK)) + +/** + * Bitfield which represents a namedata property options in an ecma_property_descriptor_t + * Attributes: + * - is_get_defined, is_set_defined : false + * - is_configurable, is_writable, is_enumerable : undefined (false) + * - is_throw : undefined (false) + * - is_value_defined : true + * - is_configurable_defined, is_writable_defined, is_enumerable_defined : true + */ +#define ECMA_NAME_DATA_PROPERTY_DESCRIPTOR_BITS \ + ((uint16_t) (JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_CONFIGURABLE_DEFINED | JERRY_PROP_IS_ENUMERABLE_DEFINED \ + | JERRY_PROP_IS_WRITABLE_DEFINED)) /** * Ecma-collection: a growable list of ecma-values. @@ -1472,251 +1325,457 @@ typedef struct #define ECMA_COMPACT_COLLECTION_GET_SIZE(compact_collection_p) \ ((compact_collection_p)[0] >> ECMA_COMPACT_COLLECTION_SIZE_SHIFT) +#if JERRY_ESNEXT /** - * Direct string types (2 bit). + * Required number of ecma values in a compact collection to represent PrivateElement */ -typedef enum +#define ECMA_PRIVATE_ELEMENT_LIST_SIZE 3 +#endif /* JERRY_ESNEXT */ + +/** + * Struct for counting the different types properties in objects + */ +typedef struct { - ECMA_DIRECT_STRING_PTR = 0, /**< string is a string pointer, only used by property names */ - ECMA_DIRECT_STRING_MAGIC = 1, /**< string is a magic string */ - ECMA_DIRECT_STRING_UINT = 2, /**< string is an unsigned int */ - ECMA_DIRECT_STRING_SPECIAL = 3, /**< string is special */ -} ecma_direct_string_type_t; + uint32_t array_index_named_props; /**< number of array index named properties */ + uint32_t string_named_props; /**< number of string named properties */ + uint32_t symbol_named_props; /**< number of symbol named properties */ +} ecma_property_counter_t; /** - * Maximum value of the immediate part of a direct magic string. - * Must be compatible with the immediate property name. + * Builtin routine function object status flags */ -#if JERRY_CPOINTER_32_BIT -#define ECMA_DIRECT_STRING_MAX_IMM 0x07ffffff -#else /* !JERRY_CPOINTER_32_BIT */ -#define ECMA_DIRECT_STRING_MAX_IMM 0x0000ffff -#endif /* JERRY_CPOINTER_32_BIT */ +typedef enum +{ + ECMA_BUILTIN_ROUTINE_NO_OPTS = 0, /**< No options are provided */ + ECMA_BUILTIN_ROUTINE_LENGTH_INITIALIZED = (1u << 0), /**< 'length' property has been initialized */ + ECMA_BUILTIN_ROUTINE_NAME_INITIALIZED = (1u << 1), /**< 'name' property has been initialized */ + ECMA_BUILTIN_ROUTINE_GETTER = (1u << 2), /**< this routine is getter */ + ECMA_BUILTIN_ROUTINE_SETTER = (1u << 3), /**< this routine is setter */ +} ecma_builtin_routine_flags_t; + +/* Standard defined internal methods */ +typedef ecma_object_t *(*ecma_internal_get_prototype_of_cb_t) (ecma_object_t *); +typedef ecma_value_t (*ecma_internal_set_prototype_of_cb_t) (ecma_object_t *, ecma_value_t); +typedef ecma_value_t (*ecma_internal_is_extensible_cb_t) (ecma_object_t *); +typedef ecma_value_t (*ecma_internal_prevent_extensions_cb_t) (ecma_object_t *); +typedef ecma_property_descriptor_t (*ecma_internal_get_own_property_cb_t) (ecma_object_t *, ecma_string_t *); +typedef ecma_value_t (*ecma_internal_define_own_property_cb_t) (ecma_object_t *, + ecma_string_t *, + const ecma_property_descriptor_t *); +typedef ecma_value_t (*ecma_internal_has_property_cb_t) (ecma_object_t *, ecma_string_t *); +typedef ecma_value_t (*ecma_internal_get_cb_t) (ecma_object_t *, ecma_string_t *, ecma_value_t); +typedef ecma_value_t (*ecma_internal_set_cb_t) (ecma_object_t *, ecma_string_t *, ecma_value_t, ecma_value_t, bool); +typedef ecma_value_t (*ecma_internal_delete_cb_t) (ecma_object_t *, ecma_string_t *, bool); +typedef ecma_collection_t *(*ecma_internal_own_property_keys_cb_t) (ecma_object_t *, jerry_property_filter_t); +typedef ecma_value_t (*ecma_internal_call_cb_t) (ecma_object_t *, ecma_value_t, const ecma_value_t *, uint32_t); +typedef ecma_value_t (*ecma_internal_construct_cb_t) (ecma_object_t *, ecma_object_t *, const ecma_value_t *, uint32_t); + +/* Implementation defined internal methods */ +typedef void (*ecma_internal_list_lazy_property_keys_cb_t) (ecma_object_t *obj_p, + ecma_collection_t *prop_names_p, + ecma_property_counter_t *prop_counter_p, + jerry_property_filter_t filter); + +typedef void (*ecma_internal_delete_lazy_property_cb_t) (ecma_object_t *, ecma_string_t *); + +/** + * Description of an object's virtual internal method table + */ +typedef struct +{ + ecma_internal_get_prototype_of_cb_t get_prototype_of; + ecma_internal_set_prototype_of_cb_t set_prototype_of; + ecma_internal_is_extensible_cb_t is_extensible; + ecma_internal_prevent_extensions_cb_t prevent_extensions; + ecma_internal_get_own_property_cb_t get_own_property; + ecma_internal_define_own_property_cb_t define_own_property; + ecma_internal_has_property_cb_t has_property; + ecma_internal_get_cb_t get; + ecma_internal_set_cb_t set; + ecma_internal_delete_cb_t delete; + ecma_internal_own_property_keys_cb_t own_property_keys; + ecma_internal_call_cb_t call; + ecma_internal_construct_cb_t construct; + + ecma_internal_list_lazy_property_keys_cb_t list_lazy_property_keys; + ecma_internal_delete_lazy_property_cb_t delete_lazy_property; +} ecma_internal_method_table_t; /** - * Shift for direct string value part in ecma_value_t. + * Start position of bit set size in length_and_bitset_size field. */ -#define ECMA_DIRECT_STRING_SHIFT (ECMA_VALUE_SHIFT + 2) +#define ECMA_BUILT_IN_BITSET_SHIFT 5 /** - * Full mask for direct strings. + * Description of extended ECMA-object. + * + * The extended object is an object with extra fields. */ -#define ECMA_DIRECT_STRING_MASK ((uintptr_t) (ECMA_DIRECT_TYPE_MASK | (0x3u << ECMA_VALUE_SHIFT))) +typedef struct +{ + ecma_object_t object; /**< object header */ + + /** + * Description of extra fields. These extra fields depend on the object type. + */ + union + { + ecma_built_in_props_t built_in; /**< built-in object part */ + + /** + * Description of objects with class. + * + * Note: + * class is a reserved word in c++, so cls is used instead + */ + struct + { + uint8_t type; /**< class type of the object */ + /** + * Description of 8 bit extra fields. These extra fields depend on the type. + */ + union + { + uint8_t arguments_flags; /**< arguments object flags */ + uint8_t error_type; /**< jerry_error_t type of native error objects */ +#if JERRY_BUILTIN_DATE + uint8_t date_flags; /**< flags for date objects */ +#endif /* JERRY_BUILTIN_DATE */ +#if JERRY_MODULE_SYSTEM + uint8_t module_state; /**< Module state */ +#endif /* JERRY_MODULE_SYSTEM */ +#if JERRY_ESNEXT + uint8_t iterator_kind; /**< type of iterator */ + uint8_t regexp_string_iterator_flags; /**< flags for RegExp string iterator */ + uint8_t promise_flags; /**< Promise object flags */ +#endif /* JERRY_ESNEXT */ +#if JERRY_BUILTIN_CONTAINER + uint8_t container_flags; /**< container object flags */ +#endif /* JERRY_BUILTIN_CONTAINER */ +#if JERRY_BUILTIN_TYPEDARRAY + uint8_t array_buffer_flags; /**< ArrayBuffer flags */ + uint8_t typedarray_type; /**< type of typed array */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + } u1; + /** + * Description of 16 bit extra fields. These extra fields depend on the type. + */ + union + { + uint16_t formal_params_number; /**< for arguments: formal parameters number */ +#if JERRY_MODULE_SYSTEM + uint16_t module_flags; /**< Module flags */ +#endif /* JERRY_MODULE_SYSTEM */ +#if JERRY_ESNEXT + uint16_t iterator_index; /**< for %Iterator%: [[%Iterator%NextIndex]] property */ + uint16_t executable_obj_flags; /**< executable object flags */ +#endif /* JERRY_ESNEXT */ +#if JERRY_BUILTIN_CONTAINER + uint16_t container_id; /**< magic string id of a container */ +#endif /* JERRY_BUILTIN_CONTAINER */ +#if JERRY_BUILTIN_TYPEDARRAY + uint16_t typedarray_flags; /**< typed array object flags */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ + } u2; + /** + * Description of 32 bit / value. These extra fields depend on the type. + */ + union + { + ecma_value_t value; /**< value of the object (e.g. boolean, number, string, etc.) */ +#if !JERRY_ESNEXT + ecma_value_t date; /**< Date object [[DateValue]] internal property */ +#endif /* !JERRY_ESNEXT */ + ecma_value_t target; /**< [[ProxyTarget]] or [[WeakRefTarget]] internal property */ +#if JERRY_BUILTIN_TYPEDARRAY + ecma_value_t arraybuffer; /**< for typedarray: ArrayBuffer reference */ +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_ESNEXT + ecma_value_t head; /**< points to the async generator task queue head item */ + ecma_value_t iterated_value; /**< for %Iterator%: [[IteratedObject]] property */ + ecma_value_t promise; /**< PromiseCapability[[Promise]] internal slot */ + ecma_value_t sync_iterator; /**< IteratorRecord [[Iterator]] internal slot for AsyncFromSyncIterator */ + ecma_value_t spread_value; /**< for spread object: spreaded element */ + int32_t tza; /**< TimeZone adjustment for date objects */ +#endif /* JERRY_ESNEXT */ + uint32_t length; /**< length related property (e.g. length of ArrayBuffer) */ + uint32_t arguments_number; /**< for arguments: arguments number */ +#if JERRY_MODULE_SYSTEM + uint32_t dfs_ancestor_index; /**< module dfs ancestor index (ES2020 15.2.1.16) */ +#endif /* JERRY_MODULE_SYSTEM */ + } u3; + } cls; + + /** + * Description of function objects. + */ + struct + { + jmem_cpointer_tag_t scope_cp; /**< function scope */ + ecma_value_t bytecode_cp; /**< function byte code */ + } function; + + /** + * Description of array objects. + */ + struct + { + uint32_t length; /**< length property value */ + uint32_t length_prop_and_hole_count; /**< length property attributes and number of array holes in + * a fast access mode array multiplied ECMA_FAST_ACCESS_HOLE_ONE */ + } array; + + /** + * Description of bound function object. + */ + struct + { + jmem_cpointer_tag_t target_function; /**< target function */ + ecma_value_t args_len_or_this; /**< length of arguments or this value */ + } bound_function; + +#if JERRY_ESNEXT + /** + * Description of implicit class constructor function. + */ + struct + { + ecma_value_t script_value; /**< script value */ + uint8_t flags; /**< constructor flags */ + } constructor_function; +#endif /* JERRY_ESNEXT */ + } u; +} ecma_extended_object_t; /** - * Create an ecma direct string. + * Description of built-in extended ECMA-object. */ -#define ECMA_CREATE_DIRECT_STRING(type, value) \ - ((uintptr_t) (ECMA_TYPE_DIRECT_STRING | ((type) << ECMA_VALUE_SHIFT) | (value) << ECMA_DIRECT_STRING_SHIFT)) +typedef struct +{ + ecma_extended_object_t extended_object; /**< extended object part */ + ecma_built_in_props_t built_in; /**< built-in object part */ +} ecma_extended_built_in_object_t; /** - * Create an ecma direct string from the given number. - * - * Note: the given number must be less or equal than ECMA_DIRECT_STRING_MAX_IMM + * Type of lexical environment with class */ -#define ECMA_CREATE_DIRECT_UINT32_STRING(uint32_number) \ - ((ecma_string_t *) ECMA_CREATE_DIRECT_STRING (ECMA_DIRECT_STRING_UINT, (uintptr_t) uint32_number)) +typedef enum +{ + ECMA_LEX_ENV_CLASS_TYPE_MODULE, /**< module object reference */ + ECMA_LEX_ENV_CLASS_TYPE_CLASS_ENV, /**< class constructor object reference */ +} ecma_lexical_environment_class_type_t; /** - * Checks whether the string is direct. + * Description of lexical environment with class */ -#define ECMA_IS_DIRECT_STRING(string_p) ((((uintptr_t) (string_p)) & 0x1) != 0) +typedef struct +{ + ecma_object_t lexical_env; /**< lexical environment header */ + uint32_t type; /**< element of ecma_lexical_environment_class_type_t */ + ecma_object_t *object_p; /**< object reference */ +} ecma_lexical_environment_class_t; /** - * Checks whether the string is direct. + * Check whether the given lexical class environment is a module */ -#define ECMA_IS_DIRECT_STRING_WITH_TYPE(string_p, type) \ - ((((uintptr_t) (string_p)) & ECMA_DIRECT_STRING_MASK) == ECMA_CREATE_DIRECT_STRING (type, 0)) +#define ECMA_LEX_ENV_CLASS_IS_MODULE(lex_env_p) \ + (((lex_env_p)->type_flags_refs & ECMA_OBJECT_FLAG_LEXICAL_ENV_HAS_DATA) \ + && ((ecma_lexical_environment_class_t *) (lex_env_p))->type == ECMA_LEX_ENV_CLASS_TYPE_MODULE) /** - * Returns the type of a direct string. + * Description of native functions */ -#define ECMA_GET_DIRECT_STRING_TYPE(string_p) ((((uintptr_t) (string_p)) >> ECMA_VALUE_SHIFT) & 0x3) +typedef struct +{ + ecma_extended_object_t extended_object; /**< extended object part */ +#if JERRY_BUILTIN_REALMS + ecma_value_t realm_value; /**< realm value */ +#endif /* JERRY_BUILTIN_REALMS */ + ecma_native_handler_t native_handler_cb; /**< external function */ +} ecma_native_function_t; /** - * Shift applied to type conversions. + * Alignment for the fast access mode array length. + * The real length is aligned up for allocating the underlying buffer. */ -#define ECMA_STRING_TYPE_CONVERSION_SHIFT (ECMA_PROPERTY_NAME_TYPE_SHIFT - ECMA_VALUE_SHIFT) +#define ECMA_FAST_ARRAY_ALIGNMENT (8) /** - * Converts direct string type to property name type. + * Align the length of the fast mode array to get the allocated size of the underlying buffer */ -#define ECMA_DIRECT_STRING_TYPE_TO_PROP_NAME_TYPE(string_p) \ - ((((uintptr_t) (string_p)) & (0x3 << ECMA_VALUE_SHIFT)) << ECMA_STRING_TYPE_CONVERSION_SHIFT) +#define ECMA_FAST_ARRAY_ALIGN_LENGTH(length) \ + (uint32_t) ((((length)) + ECMA_FAST_ARRAY_ALIGNMENT - 1) / ECMA_FAST_ARRAY_ALIGNMENT * ECMA_FAST_ARRAY_ALIGNMENT) /** - * Returns the value of a direct string. + * Compiled byte code data. */ -#define ECMA_GET_DIRECT_STRING_VALUE(string_p) (((uintptr_t) (string_p)) >> ECMA_DIRECT_STRING_SHIFT) +typedef struct +{ + uint16_t size; /**< real size >> JMEM_ALIGNMENT_LOG */ + uint16_t refs; /**< reference counter for the byte code */ + uint16_t status_flags; /**< various status flags: + * CBC_IS_FUNCTION check tells whether the byte code + * is function or regular expression. + * If function, the other flags must be CBC_CODE_FLAGS... + * If regexp, the other flags must be RE_FLAG... */ +} ecma_compiled_code_t; /** - * Maximum number of bytes that a long-utf8-string is able to store + * Description of bound function objects. */ -#define ECMA_STRING_SIZE_LIMIT UINT32_MAX - -typedef enum +typedef struct { - ECMA_STRING_CONTAINER_HEAP_UTF8_STRING, /**< actual data is on the heap as an utf-8 (cesu8) string - * maximum size is 2^16. */ - ECMA_STRING_CONTAINER_LONG_OR_EXTERNAL_STRING, /**< the string is a long string or provided externally - * and only its attributes are stored. */ - ECMA_STRING_CONTAINER_UINT32_IN_DESC, /**< string representation of an uint32 number */ - ECMA_STRING_CONTAINER_HEAP_ASCII_STRING, /**< actual data is on the heap as an ASCII string - * maximum size is 2^16. */ - ECMA_STRING_CONTAINER_MAGIC_STRING_EX, /**< the ecma-string is equal to one of external magic strings */ - ECMA_STRING_CONTAINER_SYMBOL, /**< the ecma-string is a symbol */ + ecma_extended_object_t header; /**< extended object header */ +#if JERRY_ESNEXT + ecma_value_t target_length; /**< length of target function */ +#endif /* JERRY_ESNEXT */ +} ecma_bound_function_t; - ECMA_STRING_CONTAINER__MAX = ECMA_STRING_CONTAINER_SYMBOL /**< maximum value */ -} ecma_string_container_t; +#if JERRY_SNAPSHOT_EXEC /** - * Mask for getting the container of a string. + * Description of static function objects. */ -#define ECMA_STRING_CONTAINER_MASK 0x7u +typedef struct +{ + ecma_extended_object_t header; /**< header part */ + const ecma_compiled_code_t *bytecode_p; /**< real byte code pointer */ +} ecma_static_function_t; + +#endif /* JERRY_SNAPSHOT_EXEC */ + +#if JERRY_ESNEXT /** - * Value for increasing or decreasing the reference counter. + * Description of arrow function objects. */ -#define ECMA_STRING_REF_ONE (1u << 4) +typedef struct +{ + ecma_extended_object_t header; /**< extended object header */ + ecma_value_t this_binding; /**< value of 'this' binding */ + ecma_value_t new_target; /**< value of new.target */ +} ecma_arrow_function_t; + +#if JERRY_SNAPSHOT_EXEC /** - * Maximum value of the reference counter (4294967280). + * Description of static arrow function objects. */ -#define ECMA_STRING_MAX_REF (0xFFFFFFF0) +typedef struct +{ + ecma_arrow_function_t header; + const ecma_compiled_code_t *bytecode_p; +} ecma_static_arrow_function_t; + +#endif /* JERRY_SNAPSHOT_EXEC */ + +#endif /* JERRY_ESNEXT */ +#if JERRY_BUILTIN_CONTAINER /** - * Flag that identifies that the string is static which means it is stored in JERRY_CONTEXT (string_list_cp) + * Flags for container objects */ -#define ECMA_STATIC_STRING_FLAG (1 << 3) +typedef enum +{ + ECMA_CONTAINER_FLAGS_EMPTY = (0), /** empty flags */ + ECMA_CONTAINER_FLAGS_WEAK = (1 << 0) /** container object is weak */ +} ecma_container_flags_t; /** - * Set an ecma-string as static string + * Description of map collection. */ -#define ECMA_SET_STRING_AS_STATIC(string_p) (string_p)->refs_and_container |= ECMA_STATIC_STRING_FLAG +typedef struct +{ + ecma_value_t key; /**< key value */ + ecma_value_t value; /**< value of the key */ +} ecma_container_pair_t; /** - * Checks whether the ecma-string is static string + * Size of a single element (in ecma_value_t unit). */ -#define ECMA_STRING_IS_STATIC(string_p) ((string_p)->refs_and_container & ECMA_STATIC_STRING_FLAG) +#define ECMA_CONTAINER_VALUE_SIZE 1 /** - * Returns with the container type of a string. + * Size of a key - value pair (in ecma_value_t unit). */ -#define ECMA_STRING_GET_CONTAINER(string_desc_p) \ - ((ecma_string_container_t) ((string_desc_p)->refs_and_container & ECMA_STRING_CONTAINER_MASK)) +#define ECMA_CONTAINER_PAIR_SIZE 2 /** - * Checks whether the reference counter is 1 of a string. + * Size of the internal buffer. */ -#define ECMA_STRING_IS_REF_EQUALS_TO_ONE(string_desc_p) (((string_desc_p)->refs_and_container >> 4) == 1) +#define ECMA_CONTAINER_GET_SIZE(container_p) (container_p->buffer_p[0]) /** - * Checks whether the reference counter is 1 of an extended primitive. + * Remove the size field of the internal buffer. */ -#define ECMA_EXTENDED_PRIMITIVE_IS_REF_EQUALS_TO_ONE(extended_primitive_p) \ - (((extended_primitive_p)->refs_and_type >> 3) == 1) +#define ECMA_CONTAINER_SET_SIZE(container_p, size) (container_p->buffer_p[0] = (ecma_value_t) (size)) /** - * ECMA string-value descriptor + * Number of entries of the internal buffer. */ -typedef struct -{ - /** Reference counter for the string */ - uint32_t refs_and_container; - - /** - * Actual data or identifier of it's place in container (depending on 'container' field) - */ - union - { - lit_string_hash_t hash; /**< hash of the ASCII/UTF8 string */ - uint32_t magic_string_ex_id; /**< identifier of an external magic string (lit_magic_string_ex_id_t) */ - uint32_t uint32_number; /**< uint32-represented number placed locally in the descriptor */ - } u; -} ecma_string_t; +#define ECMA_CONTAINER_ENTRY_COUNT(collection_p) (collection_p->item_count - 1) /** - * ECMA UTF8 string-value descriptor + * Pointer to the first entry of the internal buffer. */ -typedef struct -{ - ecma_string_t header; /**< string header */ - uint16_t size; /**< size of this utf-8 string in bytes */ - uint16_t length; /**< length of this utf-8 string in characters */ -} ecma_short_string_t; +#define ECMA_CONTAINER_START(collection_p) (collection_p->buffer_p + 1) + +#endif /* JERRY_BUILTIN_CONTAINER */ /** - * Long or external CESU8 string-value descriptor + * Description of an ecma-number */ -typedef struct -{ - ecma_string_t header; /**< string header */ - const lit_utf8_byte_t *string_p; /**< string data */ - lit_utf8_size_t size; /**< size of this external string in bytes */ - lit_utf8_size_t length; /**< length of this external string in characters */ -} ecma_long_string_t; +#if JERRY_NUMBER_TYPE_FLOAT64 +typedef double ecma_number_t; +#else /* !JERRY_NUMBER_TYPE_FLOAT64 */ +typedef float ecma_number_t; +#endif /* !JERRY_NUMBER_TYPE_FLOAT64 */ /** - * External UTF8 string-value descriptor + * Convert double to an ecma-number. */ -typedef struct -{ - ecma_long_string_t header; /**< long string header */ - void *user_p; /**< user pointer passed to the callback when the string is freed */ -} ecma_external_string_t; +#define DOUBLE_TO_ECMA_NUMBER_T(value) ((ecma_number_t) (value)) /** - * Header size of an ecma ASCII string + * Value '0' of ecma_number_t */ -#define ECMA_ASCII_STRING_HEADER_SIZE ((lit_utf8_size_t) (sizeof (ecma_string_t) + sizeof (uint8_t))) +#define ECMA_NUMBER_ZERO ((ecma_number_t) 0.0f) /** - * Get the size of an ecma ASCII string + * Value '1' of ecma_number_t */ -#define ECMA_ASCII_STRING_GET_SIZE(string_p) \ - ((lit_utf8_size_t) * ((lit_utf8_byte_t *) (string_p) + sizeof (ecma_string_t)) + 1) +#define ECMA_NUMBER_ONE ((ecma_number_t) 1.0f) /** - * Set the size of an ecma ASCII string + * Value '2' of ecma_number_t */ -#define ECMA_ASCII_STRING_SET_SIZE(string_p, size) \ - (*((lit_utf8_byte_t *) (string_p) + sizeof (ecma_string_t)) = (uint8_t) ((size) -1)) +#define ECMA_NUMBER_TWO ((ecma_number_t) 2.0f) /** - * Get the start position of the string buffer of an ecma ASCII string + * Value '0.5' of ecma_number_t */ -#define ECMA_ASCII_STRING_GET_BUFFER(string_p) ((lit_utf8_byte_t *) (string_p) + ECMA_ASCII_STRING_HEADER_SIZE) +#define ECMA_NUMBER_HALF ((ecma_number_t) 0.5f) /** - * Get the start position of the string buffer of an ecma UTF8 string + * Value '-1' of ecma_number_t */ -#define ECMA_SHORT_STRING_GET_BUFFER(string_p) ((lit_utf8_byte_t *) (string_p) + sizeof (ecma_short_string_t)) +#define ECMA_NUMBER_MINUS_ONE ((ecma_number_t) -1.0f) /** - * Get the start position of the string buffer of an ecma long CESU8 string + * Maximum number of characters in string representation of ecma-number */ -#define ECMA_LONG_STRING_BUFFER_START(string_p) ((lit_utf8_byte_t *) (string_p) + sizeof (ecma_long_string_t)) +#define ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER 64 /** - * ECMA extended string-value descriptor + * Maximum number of characters in string representation of ecma-uint32 */ -typedef struct -{ - ecma_string_t header; /**< string header */ - - union - { - ecma_value_t symbol_descriptor; /**< symbol descriptor string-value */ - ecma_value_t value; /**< original key value corresponds to the map key string */ - } u; -} ecma_extended_string_t; +#define ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32 10 -#if JERRY_ESNEXT /** - * Required number of ecma values in a compact collection to represent PrivateElement + * String is not a valid array index. */ -#define ECMA_PRIVATE_ELEMENT_LIST_SIZE 3 -#endif /* JERRY_ESNEXT */ +#define ECMA_STRING_NOT_ARRAY_INDEX UINT32_MAX /** * String builder header @@ -2093,18 +2152,23 @@ typedef enum #define ECMA_SYMBOL_FLAGS_MASK ((1 << ECMA_SYMBOL_FLAGS_SHIFT) - 1) #if (JERRY_STACK_LIMIT != 0) +/** + * Checks if the current stack usage is reached a limit + */ +#define ECMA_STACK_USAGE_LIMIT_REACHED() (ecma_get_current_stack_usage () > CONFIG_MEM_STACK_LIMIT) + /** * Check the current stack usage. If the limit is reached a RangeError is raised. * The macro argument specifies the return value which is usally ECMA_VALUE_ERROR or NULL. */ -#define ECMA_CHECK_STACK_USAGE_RETURN(RETURN_VALUE) \ - do \ - { \ - if (ecma_get_current_stack_usage () > CONFIG_MEM_STACK_LIMIT) \ - { \ - ecma_raise_maximum_callstack_error (); \ - return RETURN_VALUE; \ - } \ +#define ECMA_CHECK_STACK_USAGE_RETURN(RETURN_VALUE) \ + do \ + { \ + if (ECMA_STACK_USAGE_LIMIT_REACHED ()) \ + { \ + ecma_raise_maximum_callstack_error (); \ + return RETURN_VALUE; \ + } \ } while (0) /** @@ -2113,6 +2177,11 @@ typedef enum */ #define ECMA_CHECK_STACK_USAGE() ECMA_CHECK_STACK_USAGE_RETURN (ECMA_VALUE_ERROR) #else /* JERRY_STACK_LIMIT == 0) */ +/** + * If the stack limit is unlimited, this check is false + */ +#define ECMA_STACK_USAGE_LIMIT_REACHED() (false) + /** * If the stack limit is unlimited, this check is an empty macro. */ @@ -2222,16 +2291,6 @@ typedef uint32_t ecma_bigint_digit_t; #endif /* JERRY_BUILTIN_BIGINT */ -/** - * Struct for counting the different types properties in objects - */ -typedef struct -{ - uint32_t array_index_named_props; /**< number of array index named properties */ - uint32_t string_named_props; /**< number of string named properties */ - uint32_t symbol_named_props; /**< number of symbol named properties */ -} ecma_property_counter_t; - /** * Arguments object related status flags */ diff --git a/jerry-core/ecma/base/ecma-helpers.c b/jerry-core/ecma/base/ecma-helpers.c index 95fd4f4897..9a5c80121b 100644 --- a/jerry-core/ecma/base/ecma-helpers.c +++ b/jerry-core/ecma/base/ecma-helpers.c @@ -23,6 +23,7 @@ #include "ecma-globals.h" #include "ecma-lcache.h" #include "ecma-line-info.h" +#include "ecma-objects.h" #include "ecma-property-hashmap.h" #include "byte-code.h" @@ -59,8 +60,9 @@ JERRY_STATIC_ASSERT ((ECMA_OBJECT_MAX_REF + ECMA_OBJECT_REF_ONE) == ECMA_OBJECT_ JERRY_STATIC_ASSERT ((ECMA_OBJECT_REF_MASK & (ECMA_OBJECT_TYPE_MASK | ECMA_OBJECT_FLAG_EXTENSIBLE)) == 0, ecma_object_ref_mask_overlaps_with_object_type_or_extensible); -JERRY_STATIC_ASSERT (ECMA_PROPERTY_FLAGS_MASK == ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, - ecma_property_flags_mask_must_use_the_configurable_enumerable_writable_flags); +JERRY_STATIC_ASSERT (ECMA_PROPERTY_DESCRIPTOR_FLAGS_MASK + == (ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE | ECMA_PROPERTY_FLAG_DATA), + ecma_property_flags_mask_must_use_the_configurable_enumerable_writable_data_flags); /* These checks are needed by ecma_get_object_base_type. */ JERRY_STATIC_ASSERT ((int) ECMA_OBJECT_TYPE_BUILT_IN_GENERAL == ((int) ECMA_OBJECT_TYPE_GENERAL | 0x1) @@ -1197,43 +1199,348 @@ ecma_set_property_lcached (ecma_property_t *property_p, /**< property */ * @return empty property descriptor */ ecma_property_descriptor_t -ecma_make_empty_property_descriptor (void) +ecma_make_empty_define_property_descriptor (void) { ecma_property_descriptor_t prop_desc; - prop_desc.flags = 0; + prop_desc.flags = JERRY_PROP_NO_OPTS; + prop_desc.u.accessor.get = ECMA_VALUE_UNDEFINED; + prop_desc.u.accessor.set = ECMA_VALUE_UNDEFINED; prop_desc.value = ECMA_VALUE_UNDEFINED; - prop_desc.get_p = NULL; - prop_desc.set_p = NULL; return prop_desc; -} /* ecma_make_empty_property_descriptor */ +} /* ecma_make_empty_define_property_descriptor */ /** * Free values contained in the property descriptor * and make it empty property descriptor */ void -ecma_free_property_descriptor (ecma_property_descriptor_t *prop_desc_p) /**< property descriptor */ +ecma_free_define_property_descriptor (const ecma_property_descriptor_t *prop_desc_p) /**< property descriptor */ { if (prop_desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED) { ecma_free_value (prop_desc_p->value); } - if ((prop_desc_p->flags & JERRY_PROP_IS_GET_DEFINED) && prop_desc_p->get_p != NULL) + if ((prop_desc_p->flags & JERRY_PROP_IS_GET_DEFINED)) { - ecma_deref_object (prop_desc_p->get_p); + ecma_fast_free_value (prop_desc_p->u.accessor.get); } - if ((prop_desc_p->flags & JERRY_PROP_IS_SET_DEFINED) && prop_desc_p->set_p != NULL) + if ((prop_desc_p->flags & JERRY_PROP_IS_SET_DEFINED)) { - ecma_deref_object (prop_desc_p->set_p); + ecma_fast_free_value (prop_desc_p->u.accessor.set); } +} /* ecma_free_define_property_descriptor */ + +/** + * Function to make an empty property descriptor + * + * Note: + * if the property descriptor has the ECMA_PROP_DESC_FOUND, it should be freed with + * ecma_free_property_descriptor. + * + * @return property descriptor + */ +ecma_property_descriptor_t +ecma_make_empty_property_descriptor (void) +{ + ecma_property_descriptor_t prop_desc; + prop_desc.flags = ECMA_PROP_DESC_PROPERTY; + + return prop_desc; +} /* ecma_make_empty_property_descriptor */ + +/** + * Free the property descriptor which contains a virtual property + */ +extern inline void JERRY_ATTR_ALWAYS_INLINE +ecma_free_virtual_property_descriptor (ecma_property_descriptor_t *prop_desc_p) /**< property descriptor */ +{ + JERRY_ASSERT (prop_desc_p->flags & (ECMA_PROP_DESC_VIRTUAL | ECMA_PROP_DESC_PROPERTY)); - *prop_desc_p = ecma_make_empty_property_descriptor (); + if (prop_desc_p->flags & ECMA_PROP_DESC_VIRTUAL) + { + ecma_free_value (prop_desc_p->value); + } +} /* ecma_free_virtual_property_descriptor */ + +/** + * Free the property descriptor + */ +void +ecma_free_property_descriptor (ecma_property_descriptor_t *prop_desc_p) /**< property descriptor */ +{ + if (prop_desc_p->flags & ECMA_PROP_DESC_PROPERTY) + { + return; + } + + if (prop_desc_p->flags & ECMA_PROP_DESC_VIRTUAL) + { + ecma_free_value (prop_desc_p->value); + } + else + { + ecma_free_define_property_descriptor ((ecma_property_descriptor_t *) prop_desc_p); + } } /* ecma_free_property_descriptor */ +/** + * Check if the given property descriptor is enumerable + * + * @return bool + */ +bool +ecma_property_descriptor_is_enumerable (const ecma_property_descriptor_t *prop_desc_p) /**< property descriptor */ +{ + return prop_desc_p->flags & JERRY_PROP_IS_ENUMERABLE; +} /* ecma_property_descriptor_is_enumerable */ + +/** + * Check if the given property descriptor is configurable + * + * @return bool + */ +bool +ecma_property_descriptor_is_configurable (const ecma_property_descriptor_t *prop_desc_p) /**< property descriptor */ +{ + return prop_desc_p->flags & JERRY_PROP_IS_CONFIGURABLE; +} /* ecma_property_descriptor_is_configurable */ + +/** + * Check if the given property descriptor is writable + * + * @return bool + */ +bool +ecma_property_descriptor_is_writable (const ecma_property_descriptor_t *prop_desc_p) /**< property descriptor */ +{ + return prop_desc_p->flags & JERRY_PROP_IS_WRITABLE; +} /* ecma_property_descriptor_is_writable */ + +/** + * Check if the given property descriptor is a data property + * + * @return bool + */ +bool +ecma_property_descriptor_is_data_descriptor (const ecma_property_descriptor_t *prop_desc_p) /**< property descriptor */ +{ + return prop_desc_p->flags & ECMA_PROP_DESC_DATA; +} /* ecma_property_descriptor_is_data_descriptor */ + +/** + * Check if the given property descriptor is a data property + * + * @return bool + */ +bool +ecma_property_descriptor_is_accessor_descriptor ( + const ecma_property_descriptor_t *prop_desc_p) /**< property descriptor */ +{ + return (prop_desc_p->flags & (ECMA_PROP_DESC_ACCESSOR | ECMA_PROP_DESC_DATA)) != ECMA_PROP_DESC_DATA; +} /* ecma_property_descriptor_is_accessor_descriptor */ + +/** + * Check if the property descriptor is found + * + * @return bool + */ +bool +ecma_property_descriptor_found (const ecma_property_descriptor_t *prop_desc_p) /**< property descriptor */ +{ + return (prop_desc_p->flags & ECMA_PROP_DESC_FOUND); +} /* ecma_property_descriptor_found */ + +/** + * Check if the property descriptor is an error + * + * @return bool + */ +bool +ecma_property_descriptor_error (const ecma_property_descriptor_t *prop_desc_p) /**< property descriptor */ +{ + return prop_desc_p->flags & ECMA_PROP_DESC_ERROR; +} /* ecma_property_descriptor_error */ + +/** + * Get the value from the property descriptor + * + * @return property value + */ +ecma_value_t +ecma_property_descriptor_value (const ecma_property_descriptor_t *prop_desc_p) /**< property descriptor */ +{ + JERRY_ASSERT (ecma_property_descriptor_is_data_descriptor (prop_desc_p)); + + if (prop_desc_p->flags & ECMA_PROP_DESC_PROPERTY) + { + return ECMA_PROPERTY_VALUE_PTR (prop_desc_p->u.property_p)->value; + } + + return prop_desc_p->value; +} /* ecma_property_descriptor_value */ + +/** + * Get the getter function object pointer from the property descriptor + * + * @return NULL - if the getter function object is undefined + * getter function object - otherwise + */ +ecma_object_t * +ecma_property_descriptor_accessor_getter (const ecma_property_descriptor_t *prop_desc_p) /**< property descriptor */ +{ + JERRY_ASSERT (!ecma_property_descriptor_is_data_descriptor (prop_desc_p)); + JERRY_ASSERT (!(prop_desc_p->flags & ECMA_PROP_DESC_VIRTUAL)); + + if (prop_desc_p->flags & ECMA_PROP_DESC_PROPERTY) + { + ecma_getter_setter_pointers_t *get_set_pair_p = + ecma_get_named_accessor_property (ECMA_PROPERTY_VALUE_PTR (prop_desc_p->u.property_p)); + return ECMA_GET_POINTER (ecma_object_t, get_set_pair_p->getter_cp); + } + + return ecma_is_value_undefined (prop_desc_p->u.accessor.get) + ? NULL + : ecma_get_object_from_value (prop_desc_p->u.accessor.get); +} /* ecma_property_descriptor_accessor_getter */ + +/** + * Get the getter function object value from the property descriptor + * + * @return getter function object value + */ +ecma_value_t +ecma_property_descriptor_accessor_getter_value ( + const ecma_property_descriptor_t *prop_desc_p) /**< property descriptor */ +{ + JERRY_ASSERT (!ecma_property_descriptor_is_data_descriptor (prop_desc_p)); + JERRY_ASSERT (!(prop_desc_p->flags & ECMA_PROP_DESC_VIRTUAL)); + + if (prop_desc_p->flags & ECMA_PROP_DESC_PROPERTY) + { + ecma_getter_setter_pointers_t *get_set_pair_p = + ecma_get_named_accessor_property (ECMA_PROPERTY_VALUE_PTR (prop_desc_p->u.property_p)); + + if (get_set_pair_p->getter_cp == JMEM_CP_NULL) + { + return ECMA_VALUE_NULL; + } + + return ecma_make_object_value (ECMA_GET_POINTER (ecma_object_t, get_set_pair_p->getter_cp)); + } + + return prop_desc_p->u.accessor.get; +} /* ecma_property_descriptor_accessor_getter */ + +/** + * Get the setter function object pointer from the property descriptor + * + * @return NULL - if the setter function object is undefined + * setter function object - otherwise + */ +ecma_object_t * +ecma_property_descriptor_accessor_setter (const ecma_property_descriptor_t *prop_desc_p) /**< property descriptor */ +{ + JERRY_ASSERT (!ecma_property_descriptor_is_data_descriptor (prop_desc_p)); + JERRY_ASSERT (!(prop_desc_p->flags & ECMA_PROP_DESC_VIRTUAL)); + + if (prop_desc_p->flags & ECMA_PROP_DESC_PROPERTY) + { + ecma_getter_setter_pointers_t *get_set_pair_p = + ecma_get_named_accessor_property (ECMA_PROPERTY_VALUE_PTR (prop_desc_p->u.property_p)); + return ECMA_GET_POINTER (ecma_object_t, get_set_pair_p->setter_cp); + } + + return ecma_is_value_undefined (prop_desc_p->u.accessor.set) + ? NULL + : ecma_get_object_from_value (prop_desc_p->u.accessor.set); +} /* ecma_property_descriptor_accessor_setter */ + +/** + * Get the setter function object value from the property descriptor + * + * @return setter function object value + */ +ecma_value_t +ecma_property_descriptor_accessor_setter_value ( + const ecma_property_descriptor_t *prop_desc_p) /**< property descriptor */ +{ + JERRY_ASSERT (!ecma_property_descriptor_is_data_descriptor (prop_desc_p)); + JERRY_ASSERT (!(prop_desc_p->flags & ECMA_PROP_DESC_VIRTUAL)); + + if (!(prop_desc_p->flags & ECMA_PROP_DESC_PROPERTY)) + { + return prop_desc_p->u.accessor.set; + } + + ecma_getter_setter_pointers_t *get_set_pair_p = + ecma_get_named_accessor_property (ECMA_PROPERTY_VALUE_PTR (prop_desc_p->u.property_p)); + + if (get_set_pair_p->setter_cp == JMEM_CP_NULL) + { + return ECMA_VALUE_NULL; + } + + return ecma_make_object_value (ECMA_GET_POINTER (ecma_object_t, get_set_pair_p->setter_cp)); +} /* ecma_property_descriptor_accessor_setter_value */ + +/** + * Get the value contained in the property descriptor based on its type + * + * @return property descriptor value + */ +extern inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE +ecma_property_descriptor_get (const ecma_property_descriptor_t *prop_desc_p, /**< property descriptor */ + ecma_value_t receiver) /**< receiver */ +{ + JERRY_ASSERT (prop_desc_p->flags & (ECMA_PROP_DESC_VIRTUAL | ECMA_PROP_DESC_PROPERTY)); + + if (prop_desc_p->flags & ECMA_PROP_DESC_VIRTUAL) + { + return prop_desc_p->value; + } + + JERRY_ASSERT (prop_desc_p->u.property_p != NULL); + ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (prop_desc_p->u.property_p); + + if (*prop_desc_p->u.property_p & ECMA_PROPERTY_FLAG_DATA) + { + return ecma_fast_copy_value (prop_value_p->value); + } + + jmem_cpointer_t getter_cp = ecma_get_named_accessor_property (prop_value_p)->getter_cp; + + if (getter_cp == JMEM_CP_NULL) + { + return ECMA_VALUE_UNDEFINED; + } + + ecma_object_t *getter_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, getter_cp); + + return ecma_internal_method_call (getter_p, receiver, NULL, 0); +} /* ecma_property_descriptor_get */ + +/** + * Set the property descriptor's configurable and enumerable flags based on the 'flags' argument + */ +void +ecma_set_property_configurable_and_enumerable_flags (ecma_property_t *property_p, /**< property pointer */ + uint32_t flags) /**< flags */ +{ + if (flags & JERRY_PROP_IS_ENUMERABLE_DEFINED) + { + ecma_set_property_enumerable_attr (property_p, flags & JERRY_PROP_IS_ENUMERABLE); + } + + if (flags & JERRY_PROP_IS_CONFIGURABLE_DEFINED) + { + ecma_set_property_configurable_attr (property_p, flags & JERRY_PROP_IS_CONFIGURABLE); + } +} /* ecma_set_property_configurable_and_enumerable_flags */ + /** * Increase ref count of an extended primitve value. */ diff --git a/jerry-core/ecma/base/ecma-helpers.h b/jerry-core/ecma/base/ecma-helpers.h index 9a87c58e9a..827c99913a 100644 --- a/jerry-core/ecma/base/ecma-helpers.h +++ b/jerry-core/ecma/base/ecma-helpers.h @@ -482,8 +482,27 @@ bool ecma_is_property_lcached (ecma_property_t *property_p); void ecma_set_property_lcached (ecma_property_t *property_p, bool is_lcached); #endif /* JERRY_LCACHE */ +ecma_property_descriptor_t ecma_make_empty_define_property_descriptor (void); +void ecma_free_define_property_descriptor (const ecma_property_descriptor_t *prop_desc_p); + ecma_property_descriptor_t ecma_make_empty_property_descriptor (void); void ecma_free_property_descriptor (ecma_property_descriptor_t *prop_desc_p); +void ecma_free_virtual_property_descriptor (ecma_property_descriptor_t *prop_desc_p); +bool ecma_property_descriptor_is_enumerable (const ecma_property_descriptor_t *prop_desc_p); +bool ecma_property_descriptor_is_configurable (const ecma_property_descriptor_t *prop_desc_p); +bool ecma_property_descriptor_is_writable (const ecma_property_descriptor_t *prop_desc_p); +bool ecma_property_descriptor_is_data_descriptor (const ecma_property_descriptor_t *prop_desc_p); +bool ecma_property_descriptor_is_accessor_descriptor (const ecma_property_descriptor_t *prop_desc_p); +bool ecma_property_descriptor_found (const ecma_property_descriptor_t *prop_desc_p); +bool ecma_property_descriptor_error (const ecma_property_descriptor_t *prop_desc_p); +ecma_value_t ecma_property_descriptor_value (const ecma_property_descriptor_t *prop_desc_p); +ecma_object_t *ecma_property_descriptor_accessor_getter (const ecma_property_descriptor_t *prop_desc_p); +ecma_value_t ecma_property_descriptor_accessor_getter_value (const ecma_property_descriptor_t *prop_desc_p); +ecma_object_t *ecma_property_descriptor_accessor_setter (const ecma_property_descriptor_t *prop_desc_p); +ecma_value_t ecma_property_descriptor_accessor_setter_value (const ecma_property_descriptor_t *prop_desc_p); +ecma_object_t *ecma_property_descriptor_accessor_setter (const ecma_property_descriptor_t *prop_desc_p); +ecma_value_t ecma_property_descriptor_get (const ecma_property_descriptor_t *prop_desc_p, ecma_value_t receiver); +void ecma_set_property_configurable_and_enumerable_flags (ecma_property_t *property_p, uint32_t flags); void ecma_ref_extended_primitive (ecma_extended_primitive_t *primitve_p); void ecma_deref_exception (ecma_extended_primitive_t *exception_p); diff --git a/jerry-core/ecma/base/ecma-module.c b/jerry-core/ecma/base/ecma-module.c index f6413df07f..c40a9692b8 100644 --- a/jerry-core/ecma/base/ecma-module.c +++ b/jerry-core/ecma/base/ecma-module.c @@ -22,6 +22,7 @@ #include "ecma-helpers.h" #include "ecma-lex-env.h" #include "ecma-objects.h" +#include "ecma-ordinary-object.h" #include "jcontext.h" #include "lit-char-helpers.h" @@ -1455,4 +1456,191 @@ ecma_module_release_module (ecma_module_t *module_p) /**< module */ } } /* ecma_module_release_module */ +/** + * ecma module namespace object's [[GetOwnProperty]] internal method + * + * See also: + * ECMA-262 v12, 10.4.6.5 + * + * @return ecma_property_descriptor_t + */ +ecma_property_descriptor_t +ecma_module_namespace_object_get_own_property (ecma_object_t *obj_p, /**< the object */ + ecma_string_t *property_name_p) /**< property name */ +{ + ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); + + if (JERRY_UNLIKELY (ecma_prop_name_is_symbol (property_name_p))) + { + if (!ecma_op_compare_string_to_global_symbol (property_name_p, LIT_GLOBAL_SYMBOL_TO_STRING_TAG)) + { + return ecma_ordinary_object_get_own_property (obj_p, property_name_p); + } + + prop_desc.flags = ECMA_PROP_DESC_VIRTUAL_FOUND; + prop_desc.value = ecma_make_magic_string_value (LIT_MAGIC_STRING_MODULE_UL); + return prop_desc; + } + + prop_desc.u.property_p = ecma_find_named_property (obj_p, property_name_p); + + if (prop_desc.u.property_p == NULL) + { + return prop_desc; + } + + JERRY_ASSERT (ECMA_PROPERTY_IS_RAW (*prop_desc.u.property_p)); + + if (*prop_desc.u.property_p & ECMA_PROPERTY_FLAG_DATA) + { + prop_desc.flags = + ECMA_PROP_DESC_PROPERTY_FOUND | ECMA_PROPERTY_TO_PROPERTY_DESCRIPTOR_FLAGS (prop_desc.u.property_p); + return prop_desc; + } + + ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (prop_desc.u.property_p); + prop_value_p = ecma_get_property_value_from_named_reference (prop_value_p); + + if (JERRY_UNLIKELY (prop_value_p->value == ECMA_VALUE_UNINITIALIZED)) + { + ecma_raise_reference_error (ECMA_ERR_LET_CONST_NOT_INITIALIZED); + prop_desc.flags = ECMA_PROP_DESC_ERROR; + return prop_desc; + } + + prop_desc.flags = (ECMA_PROP_DESC_VIRTUAL_FOUND | ECMA_PROP_DESC_ENUMERABLE | ECMA_PROP_DESC_WRITABLE); + prop_desc.value = ecma_fast_copy_value (prop_value_p->value); + + return prop_desc; +} /* ecma_module_namespace_object_get_own_property */ + +/** + * ecma module namespace object's [[DefineOwnProperty]] internal method + * + * See also: + * ECMA-262 v12, 10.4.6.6 + * + * @return ecma value t + */ +ecma_value_t +ecma_module_namespace_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 */ +{ + if (JERRY_UNLIKELY (ecma_prop_name_is_symbol (property_name_p))) + { + return ecma_ordinary_object_define_own_property (object_p, property_name_p, property_desc_p); + } + + ecma_property_descriptor_t prop_desc = ecma_internal_method_get_own_property (object_p, property_name_p); + + if (ecma_property_descriptor_error (&prop_desc)) + { + return ECMA_VALUE_ERROR; + } + + if ((!ecma_property_descriptor_found (&prop_desc)) + || ((property_desc_p->flags & (JERRY_PROP_IS_CONFIGURABLE_DEFINED | JERRY_PROP_IS_CONFIGURABLE)) + == (JERRY_PROP_IS_CONFIGURABLE_DEFINED | JERRY_PROP_IS_CONFIGURABLE)) + || ((property_desc_p->flags & JERRY_PROP_IS_ENUMERABLE_DEFINED) == JERRY_PROP_IS_ENUMERABLE_DEFINED) + || ((property_desc_p->flags & (JERRY_PROP_IS_SET_DEFINED | JERRY_PROP_IS_GET_DEFINED)) + == (JERRY_PROP_IS_SET_DEFINED | JERRY_PROP_IS_GET_DEFINED)) + || ((property_desc_p->flags & JERRY_PROP_IS_WRITABLE_DEFINED) == JERRY_PROP_IS_WRITABLE_DEFINED)) + { + ecma_free_property_descriptor (&prop_desc); + return ecma_raise_property_redefinition (property_name_p, property_desc_p->flags); + } + + if ((property_desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED)) + { + if (!ecma_op_same_value (property_desc_p->value, ecma_property_descriptor_value (&prop_desc))) + { + ecma_free_property_descriptor (&prop_desc); + return ecma_raise_property_redefinition (property_name_p, property_desc_p->flags); + } + } + ecma_free_property_descriptor (&prop_desc); + + return ECMA_VALUE_TRUE; +} /* ecma_module_namespace_object_define_own_property */ + +/** + * ecma module namespace object's [[Get]] internal method + * + * See also: + * ECMA-262 v12, 10.4.6.8 + * + * @return ecma value t + */ +ecma_value_t +ecma_module_namespace_object_get (ecma_object_t *obj_p, /**< the object */ + ecma_string_t *property_name_p, /**< property name */ + ecma_value_t receiver) /**< receiver */ +{ + JERRY_UNUSED (receiver); + + if (JERRY_UNLIKELY (ecma_prop_name_is_symbol (property_name_p))) + { + /* ECMA-262 v11, 26.3.1 */ + if (ecma_op_compare_string_to_global_symbol (property_name_p, LIT_GLOBAL_SYMBOL_TO_STRING_TAG)) + { + return ecma_make_magic_string_value (LIT_MAGIC_STRING_MODULE_UL); + } + } + else + { + ecma_property_t *property_p = ecma_find_named_property (obj_p, property_name_p); + + if (property_p != NULL) + { + JERRY_ASSERT (ECMA_PROPERTY_IS_RAW (*property_p)); + + ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + + if (!(*property_p & ECMA_PROPERTY_FLAG_DATA)) + { + prop_value_p = ecma_get_property_value_from_named_reference (prop_value_p); + + if (JERRY_UNLIKELY (prop_value_p->value == ECMA_VALUE_UNINITIALIZED)) + { + return ecma_raise_reference_error (ECMA_ERR_LET_CONST_NOT_INITIALIZED); + } + } + + return ecma_fast_copy_value (prop_value_p->value); + } + } + + jmem_cpointer_t proto_cp = ecma_object_get_prototype_of (obj_p); + + if (proto_cp == JMEM_CP_NULL) + { + return ECMA_VALUE_UNDEFINED; + } + + ecma_object_t *proto_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, proto_cp); + + return ecma_internal_method_get (proto_p, property_name_p, receiver); +} /* ecma_module_namespace_object_get */ + +/** + * ecma module namespace object's [[Set]] internal method + * + * See also: + * ECMA-262 v12, 10.4.6.9 + * + * @return ecma value t + */ +ecma_value_t +ecma_module_namespace_object_set (ecma_object_t *obj_p, /**< the object */ + ecma_string_t *property_name_p, /**< property name */ + ecma_value_t value, /**< ecma value */ + ecma_value_t receiver, /**< receiver */ + bool is_throw) /**< flag that controls failure handling */ +{ + JERRY_UNUSED_3 (obj_p, value, receiver); + return ecma_raise_readonly_assignment (property_name_p, is_throw); +} /* ecma_module_namespace_object_set */ + #endif /* JERRY_MODULE_SYSTEM */ diff --git a/jerry-core/ecma/base/ecma-module.h b/jerry-core/ecma/base/ecma-module.h index ceb47ec669..468fe2d5ba 100644 --- a/jerry-core/ecma/base/ecma-module.h +++ b/jerry-core/ecma/base/ecma-module.h @@ -127,6 +127,39 @@ void ecma_module_cleanup_context (void); void ecma_module_release_module_names (ecma_module_names_t *module_name_p); void ecma_module_release_module (ecma_module_t *module_p); +ecma_property_descriptor_t ecma_module_namespace_object_get_own_property (ecma_object_t *obj_p, + ecma_string_t *property_name_p); +ecma_value_t ecma_module_namespace_object_define_own_property (ecma_object_t *object_p, + ecma_string_t *property_name_p, + const ecma_property_descriptor_t *property_desc_p); +ecma_value_t +ecma_module_namespace_object_get (ecma_object_t *obj_p, ecma_string_t *property_name_p, ecma_value_t receiver); +ecma_value_t ecma_module_namespace_object_set (ecma_object_t *obj_p, + ecma_string_t *property_name_p, + ecma_value_t value, + ecma_value_t receiver, + bool is_throw); + +/** + * Virtual function table for module namespace object's internal methods + */ +#define ECMA_MODULE_NAMESPACE_OBJ_VTABLE \ + [ECMA_OBJECT_CLASS_MODULE_NAMESPACE] = { NULL, \ + NULL, \ + NULL, \ + NULL, \ + ecma_module_namespace_object_get_own_property, \ + ecma_module_namespace_object_define_own_property, \ + NULL, \ + ecma_module_namespace_object_get, \ + ecma_module_namespace_object_set, \ + ecma_ordinary_object_delete, \ + NULL, \ + NULL, \ + NULL, \ + ecma_ordinary_object_list_lazy_property_keys, \ + ecma_ordinary_object_delete_lazy_property } + #endif /* JERRY_MODULE_SYSTEM */ #endif /* !ECMA_MODULE_H */ diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-array-iterator-prototype.c b/jerry-core/ecma/builtin-objects/ecma-builtin-array-iterator-prototype.c index 308845ff0b..15917e32f5 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-array-iterator-prototype.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-array-iterator-prototype.c @@ -123,14 +123,18 @@ ecma_builtin_array_iterator_prototype_object_next (ecma_value_t this_val) /**< t /* After the ECMA_ITERATOR_INDEX_LIMIT limit is reached the [[%Iterator%NextIndex]] property is stored as an internal property */ ecma_string_t *prop_name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_ITERATOR_NEXT_INDEX); - ecma_value_t index_value = ecma_op_object_get (obj_p, prop_name_p); + ecma_value_t index_value = ecma_internal_method_get (obj_p, prop_name_p, this_val); if (!ecma_is_value_undefined (index_value)) { index = (ecma_length_t) (ecma_get_number_from_value (index_value) + 1); } - ecma_value_t put_result = ecma_op_object_put (obj_p, prop_name_p, ecma_make_length_value (index), true); + ecma_value_t put_result = ecma_internal_method_set (obj_p, + prop_name_p, + ecma_make_length_value (index), + ecma_make_object_value (obj_p), + true); JERRY_ASSERT (ecma_is_value_true (put_result)); diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.c b/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.c index 7201a0c211..99c21581ba 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.c @@ -112,8 +112,11 @@ ecma_builtin_array_prototype_helper_set_length (ecma_object_t *object, /**< obje ecma_number_t length) /**< new length */ { ecma_value_t length_value = ecma_make_number_value (length); - ecma_value_t ret_value = - ecma_op_object_put (object, ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH), length_value, true); + ecma_value_t ret_value = ecma_internal_method_set (object, + ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH), + length_value, + ecma_make_object_value (object), + true); ecma_free_value (length_value); @@ -486,7 +489,8 @@ ecma_builtin_array_prototype_object_push (const ecma_value_t *argument_list_p, / { /* 5.b */ ecma_string_t *index_str_p = ecma_new_ecma_string_from_number (n); - ecma_value_t put_value = ecma_op_object_put (obj_p, index_str_p, argument_list_p[index], true); + ecma_value_t put_value = + ecma_internal_method_set (obj_p, index_str_p, argument_list_p[index], ecma_make_object_value (obj_p), true); ecma_deref_ecma_string (index_str_p); if (ECMA_IS_VALUE_ERROR (put_value)) @@ -542,6 +546,8 @@ ecma_builtin_array_prototype_object_reverse (ecma_value_t this_arg, /**< this ar } ecma_length_t middle = len / 2; + ecma_value_t obj_value = ecma_make_object_value (obj_p); + for (ecma_length_t lower = 0; lower < middle; lower++) { ecma_length_t upper = len - lower - 1; @@ -554,7 +560,7 @@ ecma_builtin_array_prototype_object_reverse (ecma_value_t this_arg, /**< this ar ecma_value_t lower_value = ECMA_VALUE_EMPTY; ecma_value_t upper_value = ECMA_VALUE_EMPTY; - ecma_value_t has_lower = ecma_op_object_has_property (obj_p, lower_str_p); + ecma_value_t has_lower = ecma_internal_method_has_property (obj_p, lower_str_p); #if JERRY_BUILTIN_PROXY if (ECMA_IS_VALUE_ERROR (has_lower)) @@ -567,7 +573,7 @@ ecma_builtin_array_prototype_object_reverse (ecma_value_t this_arg, /**< this ar if (lower_exist) { - lower_value = ecma_op_object_get (obj_p, lower_str_p); + lower_value = ecma_internal_method_get (obj_p, lower_str_p, obj_value); if (ECMA_IS_VALUE_ERROR (lower_value)) { @@ -575,7 +581,7 @@ ecma_builtin_array_prototype_object_reverse (ecma_value_t this_arg, /**< this ar } } - ecma_value_t has_upper = ecma_op_object_has_property (obj_p, upper_str_p); + ecma_value_t has_upper = ecma_internal_method_has_property (obj_p, upper_str_p); #if JERRY_BUILTIN_PROXY if (ECMA_IS_VALUE_ERROR (has_upper)) @@ -588,7 +594,7 @@ ecma_builtin_array_prototype_object_reverse (ecma_value_t this_arg, /**< this ar if (upper_exist) { - upper_value = ecma_op_object_get (obj_p, upper_str_p); + upper_value = ecma_internal_method_get (obj_p, upper_str_p, obj_value); if (ECMA_IS_VALUE_ERROR (upper_value)) { @@ -596,7 +602,7 @@ ecma_builtin_array_prototype_object_reverse (ecma_value_t this_arg, /**< this ar } } #else /* !JERRY_ESNEXT */ - ecma_value_t lower_value = ecma_op_object_get (obj_p, lower_str_p); + ecma_value_t lower_value = ecma_internal_method_get (obj_p, lower_str_p, obj_value); if (ECMA_IS_VALUE_ERROR (lower_value)) { @@ -605,30 +611,31 @@ ecma_builtin_array_prototype_object_reverse (ecma_value_t this_arg, /**< this ar return ret_value; } - ecma_value_t upper_value = ecma_op_object_get (obj_p, upper_str_p); + ecma_value_t upper_value = ecma_internal_method_get (obj_p, upper_str_p, obj_value); if (ECMA_IS_VALUE_ERROR (upper_value)) { goto clean_up; } - ecma_value_t has_lower = ecma_op_object_has_property (obj_p, lower_str_p); - ecma_value_t has_upper = ecma_op_object_has_property (obj_p, upper_str_p); + ecma_value_t has_lower = ecma_internal_method_has_property (obj_p, lower_str_p); + ecma_value_t has_upper = ecma_internal_method_has_property (obj_p, upper_str_p); bool lower_exist = ecma_is_value_true (has_lower); bool upper_exist = ecma_is_value_true (has_upper); + #endif /* JERRY_ESNEXT */ if (lower_exist && upper_exist) { - ecma_value_t outer_put_value = ecma_op_object_put (obj_p, lower_str_p, upper_value, true); + ecma_value_t outer_put_value = ecma_internal_method_set (obj_p, lower_str_p, upper_value, obj_value, true); if (ECMA_IS_VALUE_ERROR (outer_put_value)) { goto clean_up; } - ecma_value_t inner_put_value = ecma_op_object_put (obj_p, upper_str_p, lower_value, true); + ecma_value_t inner_put_value = ecma_internal_method_set (obj_p, upper_str_p, lower_value, obj_value, true); if (ECMA_IS_VALUE_ERROR (inner_put_value)) { @@ -637,14 +644,14 @@ ecma_builtin_array_prototype_object_reverse (ecma_value_t this_arg, /**< this ar } else if (!lower_exist && upper_exist) { - ecma_value_t put_value = ecma_op_object_put (obj_p, lower_str_p, upper_value, true); + ecma_value_t put_value = ecma_internal_method_set (obj_p, lower_str_p, upper_value, obj_value, true); if (ECMA_IS_VALUE_ERROR (put_value)) { goto clean_up; } - ecma_value_t del_value = ecma_op_object_delete (obj_p, upper_str_p, true); + ecma_value_t del_value = ecma_internal_method_delete (obj_p, upper_str_p, true); if (ECMA_IS_VALUE_ERROR (del_value)) { @@ -653,14 +660,14 @@ ecma_builtin_array_prototype_object_reverse (ecma_value_t this_arg, /**< this ar } else if (lower_exist) { - ecma_value_t del_value = ecma_op_object_delete (obj_p, lower_str_p, true); + ecma_value_t del_value = ecma_internal_method_delete (obj_p, lower_str_p, true); if (ECMA_IS_VALUE_ERROR (del_value)) { goto clean_up; } - ecma_value_t put_value = ecma_op_object_put (obj_p, upper_str_p, lower_value, true); + ecma_value_t put_value = ecma_internal_method_set (obj_p, upper_str_p, lower_value, obj_value, true); if (ECMA_IS_VALUE_ERROR (put_value)) { @@ -1045,7 +1052,7 @@ ecma_builtin_array_prototype_object_sort_compare_helper (ecma_value_t lhs, /**< ecma_value_t compare_args[] = { lhs, rhs }; - ecma_value_t call_value = ecma_op_function_call (comparefn_obj_p, ECMA_VALUE_UNDEFINED, compare_args, 2); + ecma_value_t call_value = ecma_internal_method_call (comparefn_obj_p, ECMA_VALUE_UNDEFINED, compare_args, 2); if (ECMA_IS_VALUE_ERROR (call_value)) { return call_value; @@ -1107,23 +1114,25 @@ ecma_builtin_array_prototype_object_sort (ecma_value_t this_arg, /**< this argum { ecma_string_t *prop_name_p = ecma_new_ecma_string_from_uint32 (i); - ecma_property_descriptor_t prop_desc; - ecma_value_t get_desc = ecma_op_object_get_own_property_descriptor (obj_p, prop_name_p, &prop_desc); + ecma_property_descriptor_t prop_desc = ecma_internal_method_get_own_property (obj_p, prop_name_p); - if (ECMA_IS_VALUE_ERROR (get_desc)) + if (ecma_property_descriptor_error (&prop_desc)) { ecma_collection_free (array_index_props_p); ecma_deref_ecma_string (prop_name_p); - return get_desc; + ecma_free_property_descriptor (&prop_desc); + return ECMA_VALUE_ERROR; } - if (ecma_is_value_true (get_desc)) + if (ecma_property_descriptor_found (&prop_desc)) { ecma_ref_ecma_string (prop_name_p); ecma_collection_push_back (array_index_props_p, ecma_make_string_value (prop_name_p)); ecma_free_property_descriptor (&prop_desc); continue; } + + ecma_free_property_descriptor (&prop_desc); } uint32_t defined_prop_count = array_index_props_p->item_count; @@ -1147,7 +1156,7 @@ ecma_builtin_array_prototype_object_sort (ecma_value_t this_arg, /**< this argum break; } - ecma_value_t index_value = ecma_op_object_get (obj_p, property_name_p); + ecma_value_t index_value = ecma_internal_method_get (obj_p, property_name_p, ecma_make_object_value (obj_p)); if (ECMA_IS_VALUE_ERROR (index_value)) { @@ -1215,7 +1224,7 @@ ecma_builtin_array_prototype_object_sort (ecma_value_t this_arg, /**< this argum if (index >= copied_num && index < len) { - ecma_value_t del_value = ecma_op_object_delete (obj_p, property_name_p, true); + ecma_value_t del_value = ecma_internal_method_delete (obj_p, property_name_p, true); if (ECMA_IS_VALUE_ERROR (del_value)) { @@ -1548,13 +1557,14 @@ ecma_builtin_array_prototype_object_unshift (const ecma_value_t args[], /**< arg if (ecma_is_value_found (get_value)) { /* ES5.1:6.d.i, 6.d.ii, ES11:4.c.iv. */ - operation_value = ecma_op_object_put (obj_p, index_str_p, get_value, true); + operation_value = + ecma_internal_method_set (obj_p, index_str_p, get_value, ecma_make_object_value (obj_p), true); ecma_free_value (get_value); } else { /* ES5.1:6.e.i, ES11:4.c.v. */ - operation_value = ecma_op_object_delete (obj_p, index_str_p, true); + operation_value = ecma_internal_method_delete (obj_p, index_str_p, true); } ecma_deref_ecma_string (index_str_p); @@ -1881,7 +1891,7 @@ ecma_builtin_array_apply (ecma_value_t arg1, /**< callbackfn */ ecma_value_t call_args[] = { get_value, current_index, ecma_make_object_value (obj_p) }; /* 7.c.ii */ - ecma_value_t call_value = ecma_op_function_call (func_object_p, arg2, call_args, 3); + ecma_value_t call_value = ecma_internal_method_call (func_object_p, arg2, call_args, 3); if (ECMA_IS_VALUE_ERROR (call_value)) { @@ -1977,7 +1987,7 @@ ecma_builtin_array_prototype_object_map (ecma_value_t arg1, /**< callbackfn */ current_index = ecma_make_length_value (index); ecma_value_t call_args[] = { current_value, current_index, ecma_make_object_value (obj_p) }; - ecma_value_t mapped_value = ecma_op_function_call (func_object_p, arg2, call_args, 3); + ecma_value_t mapped_value = ecma_internal_method_call (func_object_p, arg2, call_args, 3); if (ECMA_IS_VALUE_ERROR (mapped_value)) { @@ -2078,7 +2088,7 @@ ecma_builtin_array_prototype_object_filter (ecma_value_t arg1, /**< callbackfn * ecma_value_t call_args[] = { get_value, current_index, ecma_make_object_value (obj_p) }; /* 9.c.ii */ - ecma_value_t call_value = ecma_op_function_call (func_object_p, arg2, call_args, 3); + ecma_value_t call_value = ecma_internal_method_call (func_object_p, arg2, call_args, 3); if (ECMA_IS_VALUE_ERROR (call_value)) { @@ -2218,7 +2228,7 @@ ecma_builtin_array_reduce_from (const ecma_value_t args_p[], /**< routine's argu current_index = ecma_make_length_value (corrected_index); ecma_value_t call_args[] = { accumulator, current_value, current_index, ecma_make_object_value (obj_p) }; - ecma_value_t call_value = ecma_op_function_call (func_object_p, ECMA_VALUE_UNDEFINED, call_args, 4); + ecma_value_t call_value = ecma_internal_method_call (func_object_p, ECMA_VALUE_UNDEFINED, call_args, 4); ecma_free_value (current_index); ecma_free_value (accumulator); ecma_free_value (current_value); @@ -2368,7 +2378,7 @@ ecma_builtin_array_prototype_object_find (ecma_value_t predicate, /**< callback ecma_value_t call_args[] = { get_value, current_index, ecma_make_object_value (obj_p) }; - ecma_value_t call_value = ecma_op_function_call (func_object_p, predicate_this_arg, call_args, 3); + ecma_value_t call_value = ecma_internal_method_call (func_object_p, predicate_this_arg, call_args, 3); if (ECMA_IS_VALUE_ERROR (call_value)) { @@ -2687,7 +2697,8 @@ ecma_builtin_array_flatten_into_array (ecma_value_t target, /**< target will con /* i-ii. */ ecma_value_t source_val = ecma_make_length_value (source_index); ecma_value_t args[] = { element, source_val, ecma_make_object_value (source) }; - ecma_value_t temp_element = ecma_op_function_call (ecma_get_object_from_value (mapped_value), thisArg, args, 3); + ecma_value_t temp_element = + ecma_internal_method_call (ecma_get_object_from_value (mapped_value), thisArg, args, 3); ecma_free_value (element); ecma_free_value (source_val); diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-array.c b/jerry-core/ecma/builtin-objects/ecma-builtin-array.c index bfd782e873..3851087e78 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-array.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-array.c @@ -131,7 +131,7 @@ ecma_builtin_array_object_from (ecma_value_t this_arg, /**< 'this' argument */ { ecma_object_t *constructor_obj_p = ecma_get_object_from_value (constructor); - ecma_value_t array = ecma_op_function_construct (constructor_obj_p, constructor_obj_p, NULL, 0); + ecma_value_t array = ecma_internal_method_construct (constructor_obj_p, constructor_obj_p, NULL, 0); if (ecma_is_value_undefined (array) || ecma_is_value_null (array)) { @@ -186,8 +186,11 @@ ecma_builtin_array_object_from (ecma_value_t this_arg, /**< 'this' argument */ { /* 6.g.iv.1 */ ecma_value_t len_value = ecma_make_uint32_value (k); - ecma_value_t set_status = - ecma_op_object_put (array_obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH), len_value, true); + ecma_value_t set_status = ecma_internal_method_set (array_obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH), + len_value, + ecma_make_object_value (array_obj_p), + true); ecma_free_value (len_value); /* 6.g.iv.2 */ @@ -220,7 +223,7 @@ ecma_builtin_array_object_from (ecma_value_t this_arg, /**< 'this' argument */ /* 6.g.vii.1 */ ecma_value_t args_p[2] = { next_value, ecma_make_uint32_value (k) }; /* 6.g.vii.3 */ - mapped_value = ecma_op_function_call (mapfn_obj_p, call_this_arg, args_p, 2); + mapped_value = ecma_internal_method_call (mapfn_obj_p, call_this_arg, args_p, 2); ecma_free_value (args_p[1]); ecma_free_value (next_value); @@ -292,7 +295,7 @@ ecma_builtin_array_object_from (ecma_value_t this_arg, /**< 'this' argument */ ecma_object_t *constructor_obj_p = ecma_get_object_from_value (constructor); len_value = ecma_make_length_value (len); - ecma_value_t array = ecma_op_function_construct (constructor_obj_p, constructor_obj_p, &len_value, 1); + ecma_value_t array = ecma_internal_method_construct (constructor_obj_p, constructor_obj_p, &len_value, 1); ecma_free_value (len_value); if (ecma_is_value_undefined (array) || ecma_is_value_null (array)) @@ -341,7 +344,7 @@ ecma_builtin_array_object_from (ecma_value_t this_arg, /**< 'this' argument */ { /* 16.d.i */ ecma_value_t args_p[2] = { k_value, ecma_make_length_value (k) }; - mapped_value = ecma_op_function_call (mapfn_obj_p, call_this_arg, args_p, 2); + mapped_value = ecma_internal_method_call (mapfn_obj_p, call_this_arg, args_p, 2); ecma_free_value (args_p[1]); ecma_free_value (k_value); @@ -375,8 +378,11 @@ ecma_builtin_array_object_from (ecma_value_t this_arg, /**< 'this' argument */ /* 17. */ len_value = ecma_make_length_value (k); - ecma_value_t set_status = - ecma_op_object_put (array_obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH), len_value, true); + ecma_value_t set_status = ecma_internal_method_set (array_obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH), + len_value, + ecma_make_object_value (array_obj_p), + true); ecma_free_value (len_value); /* 18. */ @@ -417,8 +423,10 @@ ecma_builtin_array_object_of (ecma_value_t this_arg, /**< 'this' argument */ ecma_value_t len = ecma_make_uint32_value (arguments_list_len); - ecma_value_t ret_val = - ecma_op_function_construct (ecma_get_object_from_value (this_arg), ecma_get_object_from_value (this_arg), &len, 1); + ecma_value_t ret_val = ecma_internal_method_construct (ecma_get_object_from_value (this_arg), + ecma_get_object_from_value (this_arg), + &len, + 1); if (ECMA_IS_VALUE_ERROR (ret_val)) { @@ -445,7 +453,11 @@ ecma_builtin_array_object_of (ecma_value_t this_arg, /**< 'this' argument */ k++; } - ret_val = ecma_op_object_put (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH), len, true); + ret_val = ecma_internal_method_set (obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH), + len, + ecma_make_object_value (obj_p), + true); ecma_free_value (len); diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-async-from-sync-iterator-prototype.c b/jerry-core/ecma/builtin-objects/ecma-builtin-async-from-sync-iterator-prototype.c index 034df50402..82663c65e3 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-async-from-sync-iterator-prototype.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-async-from-sync-iterator-prototype.c @@ -23,6 +23,7 @@ #include "ecma-globals.h" #include "ecma-helpers.h" #include "ecma-iterator-object.h" +#include "ecma-native-function.h" #include "ecma-objects.h" #include "ecma-promise-object.h" @@ -114,8 +115,8 @@ ecma_op_async_from_sync_iterator_prototype_continuation (ecma_value_t result, /* } /* 8 - 9. */ - ecma_object_t *on_fullfilled = ecma_op_create_native_handler (ECMA_NATIVE_HANDLER_ASYNC_FROM_SYNC_ITERATOR_UNWRAP, - sizeof (ecma_extended_object_t)); + ecma_object_t *on_fullfilled = + ecma_native_function_create (ECMA_NATIVE_HANDLER_ASYNC_FROM_SYNC_ITERATOR_UNWRAP, sizeof (ecma_extended_object_t)); ((ecma_extended_object_t *) on_fullfilled)->u.built_in.u2.routine_flags = (uint8_t) done_flag; /* 10. */ @@ -226,7 +227,7 @@ ecma_builtin_async_from_sync_iterator_prototype_do (ecma_async_from_sync_iterato /* 7.b. */ ecma_value_t resolve = - ecma_op_function_call (ecma_get_object_from_value (func_obj), ECMA_VALUE_UNDEFINED, &call_arg, arg_size); + ecma_internal_method_call (ecma_get_object_from_value (func_obj), ECMA_VALUE_UNDEFINED, &call_arg, arg_size); JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (resolve)); ecma_free_value (resolve); @@ -240,7 +241,7 @@ ecma_builtin_async_from_sync_iterator_prototype_do (ecma_async_from_sync_iterato } /* 8. */ - ecma_value_t call_result = ecma_op_function_validated_call (method, sync_iterator, &call_arg, arg_size); + ecma_value_t call_result = ecma_internal_method_validated_call (method, sync_iterator, &call_arg, arg_size); ecma_free_value (method); /* 9. */ @@ -271,8 +272,10 @@ ecma_builtin_async_from_sync_iterator_prototype_do (ecma_async_from_sync_iterato ecma_value_t type_error = ecma_make_object_value (type_error_obj_p); /* 10.a. */ - ecma_value_t reject = - ecma_op_function_call (ecma_get_object_from_value (capability_p->reject), ECMA_VALUE_UNDEFINED, &type_error, 1); + ecma_value_t reject = ecma_internal_method_call (ecma_get_object_from_value (capability_p->reject), + ECMA_VALUE_UNDEFINED, + &type_error, + 1); JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (reject)); ecma_deref_object (type_error_obj_p); ecma_free_value (reject); diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.c b/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.c index 8910eaaa74..131a881444 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.c @@ -211,7 +211,7 @@ ecma_builtin_function_prototype_object_apply (ecma_object_t *func_obj_p, /**< th /* 2. */ if (ecma_is_value_null (arg2) || ecma_is_value_undefined (arg2)) { - return ecma_op_function_call (func_obj_p, arg1, NULL, 0); + return ecma_internal_method_call (func_obj_p, arg1, NULL, 0); } /* 3. */ @@ -258,7 +258,7 @@ ecma_builtin_function_prototype_object_apply (ecma_object_t *func_obj_p, /**< th if (ecma_is_value_empty (ret_value)) { JERRY_ASSERT (index == length); - ret_value = ecma_op_function_call (func_obj_p, arg1, arguments_list_p, (uint32_t) length); + ret_value = ecma_internal_method_call (func_obj_p, arg1, arguments_list_p, (uint32_t) length); } for (uint32_t remove_index = 0; remove_index < index; remove_index++) @@ -288,13 +288,13 @@ ecma_builtin_function_prototype_object_call (ecma_object_t *func_obj_p, /**< thi if (arguments_number == 0) { /* Even a 'this' argument is missing. */ - return ecma_op_function_call (func_obj_p, ECMA_VALUE_UNDEFINED, NULL, 0); + return ecma_internal_method_call (func_obj_p, ECMA_VALUE_UNDEFINED, NULL, 0); } - return ecma_op_function_call (func_obj_p, - arguments_list_p[0], - arguments_list_p + 1, - (uint32_t) (arguments_number - 1u)); + return ecma_internal_method_call (func_obj_p, + arguments_list_p[0], + arguments_list_p + 1, + (uint32_t) (arguments_number - 1u)); } /* ecma_builtin_function_prototype_object_call */ /** @@ -317,33 +317,14 @@ ecma_builtin_function_prototype_object_bind (ecma_object_t *this_arg_obj_p, /**< #if !JERRY_ESNEXT prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE); #else /* JERRY_ESNEXT */ -#if JERRY_BUILTIN_PROXY - if (ECMA_OBJECT_IS_PROXY (this_arg_obj_p)) - { - ecma_value_t proto = ecma_proxy_object_get_prototype_of (this_arg_obj_p); + prototype_obj_p = ecma_internal_method_get_prototype_of (this_arg_obj_p); - if (ECMA_IS_VALUE_ERROR (proto)) - { - return proto; - } - prototype_obj_p = ecma_is_value_null (proto) ? NULL : ecma_get_object_from_value (proto); - } - else - { -#endif /* JERRY_BUILTIN_PROXY */ - jmem_cpointer_t proto_cp = ecma_op_ordinary_object_get_prototype_of (this_arg_obj_p); - if (proto_cp != JMEM_CP_NULL) - { - prototype_obj_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, proto_cp); - ecma_ref_object (prototype_obj_p); - } - else - { - prototype_obj_p = NULL; - } #if JERRY_BUILTIN_PROXY + if (prototype_obj_p == ECMA_OBJECT_POINTER_ERROR) + { + return ECMA_VALUE_ERROR; } -#endif /* JERRY_BUILTIN_PROXY */ +#endif /* JERRY_BUILTIN_PROXY*/ #endif /* !JERRY_ESNEXT */ ecma_object_t *function_p; @@ -399,21 +380,21 @@ ecma_builtin_function_prototype_object_bind (ecma_object_t *this_arg_obj_p, /**< bound_func_p->target_length = ecma_make_integer_value (0); ecma_string_t *len_string = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH); - ecma_property_descriptor_t prop_desc; - ecma_value_t status = ecma_op_object_get_own_property_descriptor (this_arg_obj_p, len_string, &prop_desc); -#if JERRY_BUILTIN_PROXY - if (ECMA_IS_VALUE_ERROR (status)) + ecma_property_descriptor_t prop_desc = ecma_internal_method_get_own_property (this_arg_obj_p, len_string); + + if (ecma_property_descriptor_error (&prop_desc)) { ecma_deref_object (function_p); - return status; + ecma_free_property_descriptor (&prop_desc); + return ECMA_VALUE_ERROR; } -#endif /* JERRY_BUILTIN_PROXY */ - if (ecma_is_value_true (status)) + if (ecma_property_descriptor_found (&prop_desc)) { ecma_free_property_descriptor (&prop_desc); - ecma_value_t len_value = ecma_op_object_get (this_arg_obj_p, len_string); + ecma_value_t len_value = + ecma_internal_method_get (this_arg_obj_p, len_string, ecma_make_object_value (this_arg_obj_p)); if (ECMA_IS_VALUE_ERROR (len_value)) { @@ -430,6 +411,8 @@ ecma_builtin_function_prototype_object_bind (ecma_object_t *this_arg_obj_p, /**< ecma_free_value (len_value); } + ecma_free_property_descriptor (&prop_desc); + /* 12. */ ecma_value_t name_value = ecma_op_object_get_by_magic_id (this_arg_obj_p, LIT_MAGIC_STRING_NAME); if (ECMA_IS_VALUE_ERROR (name_value)) diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.c b/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.c index 90104af4bd..8d766172ec 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.c @@ -883,7 +883,7 @@ ecma_builtin_helper_def_prop (ecma_object_t *obj_p, /**< object */ prop_desc.value = value; - return ecma_op_object_define_own_property (obj_p, name_p, &prop_desc); + return ecma_internal_method_define_own_property (obj_p, name_p, &prop_desc); } /* ecma_builtin_helper_def_prop */ /** diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-json.c b/jerry-core/ecma/builtin-objects/ecma-builtin-json.c index 2dfa053a82..b6b987fdff 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-json.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-json.c @@ -639,7 +639,7 @@ ecma_builtin_json_internalize_property (ecma_object_t *reviver_p, /**< reviver f ECMA_CHECK_STACK_USAGE (); /* 1. */ - ecma_value_t value = ecma_op_object_get (holder_p, name_p); + ecma_value_t value = ecma_internal_method_get (holder_p, name_p, ecma_make_object_value (holder_p)); /* 2. */ if (ECMA_IS_VALUE_ERROR (value)) @@ -739,7 +739,7 @@ ecma_builtin_json_internalize_property (ecma_object_t *reviver_p, /**< reviver f arguments_list[1] = value; /* 4. */ - ecma_value_t ret_value = ecma_op_function_call (reviver_p, ecma_make_object_value (holder_p), arguments_list, 2); + ecma_value_t ret_value = ecma_internal_method_call (reviver_p, ecma_make_object_value (holder_p), arguments_list, 2); ecma_free_value (value); return ret_value; } /* ecma_builtin_json_internalize_property */ @@ -771,7 +771,7 @@ ecma_builtin_json_internalize_process_property (ecma_object_t *reviver_p, /**< r if (ecma_is_value_undefined (new_element)) { /* ES11: 2.b.iii.2.a / 2.c.ii.2.a */ - ecma_value_t delete_val = ecma_op_object_delete (object_p, prop_name, false); + ecma_value_t delete_val = ecma_internal_method_delete (object_p, prop_name, false); #if JERRY_ESNEXT if (ECMA_IS_VALUE_ERROR (delete_val)) @@ -1246,7 +1246,7 @@ ecma_builtin_json_serialize_property (ecma_json_stringify_context_t *context_p, ecma_string_t *key_p) /**< property key*/ { /* 1. */ - ecma_value_t value = ecma_op_object_get (holder_p, key_p); + ecma_value_t value = ecma_internal_method_get (holder_p, key_p, ecma_make_object_value (holder_p)); /* 2. */ if (ECMA_IS_VALUE_ERROR (value)) @@ -1267,7 +1267,7 @@ ecma_builtin_json_serialize_property (ecma_json_stringify_context_t *context_p, ecma_object_t *value_obj_p = ecma_get_object_from_value (to_object_value); ecma_value_t to_json = - ecma_op_object_get_with_receiver (value_obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_TO_JSON_UL), value); + ecma_internal_method_get (value_obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_TO_JSON_UL), value); ecma_deref_object (value_obj_p); @@ -1284,7 +1284,7 @@ ecma_builtin_json_serialize_property (ecma_json_stringify_context_t *context_p, ecma_value_t call_args[] = { key_value }; ecma_object_t *to_json_obj_p = ecma_get_object_from_value (to_json); - ecma_value_t result = ecma_op_function_call (to_json_obj_p, value, call_args, 1); + ecma_value_t result = ecma_internal_method_call (to_json_obj_p, value, call_args, 1); ecma_free_value (value); if (ECMA_IS_VALUE_ERROR (result)) @@ -1304,7 +1304,7 @@ ecma_builtin_json_serialize_property (ecma_json_stringify_context_t *context_p, ecma_value_t key_value = ecma_make_string_value (key_p); ecma_value_t call_args[] = { key_value, value }; - ecma_value_t result = ecma_op_function_call (context_p->replacer_function_p, holder_value, call_args, 2); + ecma_value_t result = ecma_internal_method_call (context_p->replacer_function_p, holder_value, call_args, 2); ecma_free_value (value); if (ECMA_IS_VALUE_ERROR (result)) diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-object-prototype.c b/jerry-core/ecma/builtin-objects/ecma-builtin-object-prototype.c index e57af2ec35..bc2c0409e1 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-object-prototype.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-object-prototype.c @@ -119,22 +119,6 @@ ecma_builtin_object_prototype_object_to_locale_string (ecma_value_t this_arg) /* return ecma_op_invoke_by_magic_id (this_arg, LIT_MAGIC_STRING_TO_STRING_UL, &this_arg, 1); } /* ecma_builtin_object_prototype_object_to_locale_string */ -/** - * The Object.prototype object's 'hasOwnProperty' routine - * - * See also: - * ECMA-262 v5, 15.2.4.5 - * - * @return ecma value - * Returned value must be freed with ecma_free_value. - */ -static ecma_value_t -ecma_builtin_object_prototype_object_has_own_property (ecma_object_t *obj_p, /**< this argument */ - ecma_string_t *prop_name_p) /**< first argument */ -{ - return ecma_op_object_has_own_property (obj_p, prop_name_p); -} /* ecma_builtin_object_prototype_object_has_own_property */ - /** * The Object.prototype object's 'isPrototypeOf' routine * @@ -178,19 +162,26 @@ static ecma_value_t ecma_builtin_object_prototype_object_property_is_enumerable (ecma_object_t *obj_p, /**< this argument */ ecma_string_t *prop_name_p) /**< first argument */ { - ecma_property_descriptor_t prop_desc; - ecma_value_t status = ecma_op_object_get_own_property_descriptor (obj_p, prop_name_p, &prop_desc); + ecma_property_descriptor_t prop_desc = ecma_internal_method_get_own_property (obj_p, prop_name_p); + + ecma_value_t ret_value; - if (!ecma_is_value_true (status)) + if (ecma_property_descriptor_error (&prop_desc)) { - return status; + ret_value = ECMA_VALUE_ERROR; + } + else if (!ecma_property_descriptor_found (&prop_desc)) + { + ret_value = ECMA_VALUE_FALSE; + } + else + { + ret_value = ecma_make_boolean_value (ecma_property_descriptor_is_enumerable (&prop_desc)); } - - bool is_enumerable = (prop_desc.flags & JERRY_PROP_IS_ENUMERABLE); ecma_free_property_descriptor (&prop_desc); - return ecma_make_boolean_value (is_enumerable); + return ret_value; } /* ecma_builtin_object_prototype_object_property_is_enumerable */ #if JERRY_ESNEXT && JERRY_BUILTIN_ANNEXB @@ -228,21 +219,19 @@ ecma_builtin_object_prototype_define_getter_setter (ecma_value_t this_arg, /**< return ecma_raise_type_error (ECMA_ERR_GETTER_IS_NOT_CALLABLE); } - ecma_object_t *accessor_obj_p = ecma_get_object_from_value (accessor); - /* 3. */ - ecma_property_descriptor_t desc = ecma_make_empty_property_descriptor (); + ecma_property_descriptor_t desc = ecma_make_empty_define_property_descriptor (); desc.flags |= (JERRY_PROP_IS_ENUMERABLE | JERRY_PROP_IS_CONFIGURABLE | JERRY_PROP_IS_ENUMERABLE_DEFINED | JERRY_PROP_IS_CONFIGURABLE_DEFINED | JERRY_PROP_SHOULD_THROW); if (define_getter) { - desc.get_p = accessor_obj_p; + desc.u.accessor.get = accessor; desc.flags |= JERRY_PROP_IS_GET_DEFINED; } else { - desc.set_p = accessor_obj_p; + desc.u.accessor.set = accessor; desc.flags |= JERRY_PROP_IS_SET_DEFINED; } @@ -256,7 +245,7 @@ ecma_builtin_object_prototype_define_getter_setter (ecma_value_t this_arg, /**< } /* 5. */ - ecma_value_t define_prop = ecma_op_object_define_own_property (obj_p, prop_name_p, &desc); + ecma_value_t define_prop = ecma_internal_method_define_own_property (obj_p, prop_name_p, &desc); ecma_deref_object (obj_p); ecma_deref_ecma_string (prop_name_p); @@ -314,40 +303,45 @@ ecma_builtin_object_prototype_lookup_getter_setter (ecma_value_t this_arg, /**< while (true) { /* 3.a */ - ecma_property_descriptor_t desc; - ecma_value_t get_desc = ecma_op_object_get_own_property_descriptor (obj_p, prop_name_p, &desc); + ecma_property_descriptor_t prop_desc = ecma_internal_method_get_own_property (obj_p, prop_name_p); - if (ECMA_IS_VALUE_ERROR (get_desc)) + if (ecma_property_descriptor_error (&prop_desc)) { - ret_value = get_desc; + ret_value = ECMA_VALUE_ERROR; + ecma_free_property_descriptor (&prop_desc); ecma_deref_object (obj_p); break; } /* 3.b */ - if (ecma_is_value_true (get_desc)) + if (ecma_property_descriptor_found (&prop_desc)) { - if ((desc.flags & JERRY_PROP_IS_SET_DEFINED) || (desc.flags & JERRY_PROP_IS_GET_DEFINED)) + if (!ecma_property_descriptor_is_data_descriptor (&prop_desc)) { - if (lookup_getter && desc.get_p != NULL) + ecma_object_t *getter_p = ecma_property_descriptor_accessor_getter (&prop_desc); + ecma_object_t *setter_p = ecma_property_descriptor_accessor_setter (&prop_desc); + + if (lookup_getter && getter_p != NULL) { - ecma_ref_object (desc.get_p); - ret_value = ecma_make_object_value (desc.get_p); + ecma_ref_object (getter_p); + ret_value = ecma_make_object_value (getter_p); } - else if (!lookup_getter && desc.set_p != NULL) + else if (!lookup_getter && setter_p != NULL) { - ecma_ref_object (desc.set_p); - ret_value = ecma_make_object_value (desc.set_p); + ecma_ref_object (setter_p); + ret_value = ecma_make_object_value (setter_p); } } - ecma_free_property_descriptor (&desc); + ecma_free_property_descriptor (&prop_desc); ecma_deref_object (obj_p); break; } + ecma_free_property_descriptor (&prop_desc); + /* 3.c */ - ecma_object_t *proto_p = ecma_op_object_get_prototype_of (obj_p); + ecma_object_t *proto_p = ecma_internal_method_get_prototype_of (obj_p); ecma_deref_object (obj_p); if (proto_p == NULL) @@ -497,7 +491,7 @@ ecma_builtin_object_prototype_dispatch_routine (uint8_t builtin_routine_id, /**< if (builtin_routine_id == ECMA_OBJECT_PROTOTYPE_HAS_OWN_PROPERTY) { - ret_value = ecma_builtin_object_prototype_object_has_own_property (obj_p, prop_name_p); + ret_value = ecma_op_object_has_own_property (obj_p, prop_name_p); } else { diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-object.c b/jerry-core/ecma/builtin-objects/ecma-builtin-object.c index e355e6871e..d395492a0c 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-object.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-object.c @@ -157,23 +157,21 @@ ecma_builtin_object_dispatch_construct (const ecma_value_t *arguments_list_p, /* ecma_value_t ecma_builtin_object_object_get_prototype_of (ecma_object_t *obj_p) /**< routine's argument */ { -#if JERRY_BUILTIN_PROXY - if (ECMA_OBJECT_IS_PROXY (obj_p)) + ecma_object_t *proto_p = ecma_internal_method_get_prototype_of (obj_p); + + if (proto_p == NULL) { - return ecma_proxy_object_get_prototype_of (obj_p); + return ECMA_VALUE_NULL; } -#endif /* JERRY_BUILTIN_PROXY */ - jmem_cpointer_t proto_cp = ecma_op_ordinary_object_get_prototype_of (obj_p); - - if (proto_cp != JMEM_CP_NULL) +#if JERRY_BUILTIN_PROXY + if (proto_p == ECMA_OBJECT_POINTER_ERROR) { - ecma_object_t *prototype_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, proto_cp); - ecma_ref_object (prototype_p); - return ecma_make_object_value (prototype_p); + return ECMA_VALUE_ERROR; } +#endif /* JERRY_BUILTIN_PROXY */ - return ECMA_VALUE_NULL; + return ecma_make_object_value (proto_p); } /* ecma_builtin_object_object_get_prototype_of */ #if JERRY_ESNEXT @@ -209,26 +207,13 @@ ecma_builtin_object_object_set_prototype_of (ecma_value_t arg1, /**< routine's f } ecma_object_t *obj_p = ecma_get_object_from_value (arg1); - ecma_value_t status; - /* 5. */ -#if JERRY_BUILTIN_PROXY - if (ECMA_OBJECT_IS_PROXY (obj_p)) - { - status = ecma_proxy_object_set_prototype_of (obj_p, arg2); + ecma_value_t status = ecma_internal_method_set_prototype_of (obj_p, arg2); - if (ECMA_IS_VALUE_ERROR (status)) - { - return status; - } - } - else + if (ECMA_IS_VALUE_ERROR (status)) { -#endif /* JERRY_BUILTIN_PROXY */ - status = ecma_op_ordinary_object_set_prototype_of (obj_p, arg2); -#if JERRY_BUILTIN_PROXY + return status; } -#endif /* JERRY_BUILTIN_PROXY */ if (ecma_is_value_false (status)) { @@ -273,24 +258,14 @@ ecma_builtin_object_object_set_proto (ecma_value_t arg1, /**< routine's first ar } ecma_object_t *obj_p = ecma_get_object_from_value (arg1); - ecma_value_t status; /* 5. */ -#if JERRY_BUILTIN_PROXY - if (ECMA_OBJECT_IS_PROXY (obj_p)) - { - status = ecma_proxy_object_set_prototype_of (obj_p, arg2); + ecma_value_t status = ecma_internal_method_set_prototype_of (obj_p, arg2); - if (ECMA_IS_VALUE_ERROR (status)) - { - return status; - } - } - else - { -#endif /* JERRY_BUILTIN_PROXY */ - status = ecma_op_ordinary_object_set_prototype_of (obj_p, arg2); #if JERRY_BUILTIN_PROXY + if (ECMA_IS_VALUE_ERROR (status)) + { + return status; } #endif /* JERRY_BUILTIN_PROXY */ @@ -320,24 +295,15 @@ ecma_builtin_object_set_integrity_level (ecma_object_t *obj_p, /**< object */ * false - set "frozen" */ { /* 3. */ -#if JERRY_BUILTIN_PROXY - if (ECMA_OBJECT_IS_PROXY (obj_p)) - { - ecma_value_t status = ecma_proxy_object_prevent_extensions (obj_p); + ecma_value_t prevent_extensions_res = ecma_internal_method_prevent_extensions (obj_p); - if (!ecma_is_value_true (status)) - { - return status; - } - } - else -#endif /* JERRY_BUILTIN_PROXY */ + if (!ecma_is_value_true (prevent_extensions_res)) { - ecma_op_ordinary_object_prevent_extensions (obj_p); + return prevent_extensions_res; } /* 6. */ - ecma_collection_t *props_p = ecma_op_object_own_property_keys (obj_p, JERRY_PROPERTY_FILTER_ALL); + ecma_collection_t *props_p = ecma_internal_method_own_property_keys (obj_p, JERRY_PROPERTY_FILTER_ALL); #if JERRY_BUILTIN_PROXY if (props_p == NULL) @@ -355,30 +321,43 @@ ecma_builtin_object_set_integrity_level (ecma_object_t *obj_p, /**< object */ { ecma_string_t *property_name_p = ecma_get_prop_name_from_value (buffer_p[i]); - ecma_property_descriptor_t prop_desc; - ecma_value_t status = ecma_op_object_get_own_property_descriptor (obj_p, property_name_p, &prop_desc); + ecma_property_descriptor_t prop_desc = ecma_internal_method_get_own_property (obj_p, property_name_p); -#if JERRY_BUILTIN_PROXY - if (ECMA_IS_VALUE_ERROR (status)) + if (ecma_property_descriptor_error (&prop_desc)) { ecma_collection_free (props_p); + ecma_free_property_descriptor (&prop_desc); return ECMA_VALUE_ERROR; } -#endif /* JERRY_BUILTIN_PROXY */ - if (ecma_is_value_false (status)) + if (!ecma_property_descriptor_found (&prop_desc)) { + ecma_free_property_descriptor (&prop_desc); continue; } - prop_desc.flags &= (uint16_t) ~JERRY_PROP_IS_CONFIGURABLE; - prop_desc.flags |= JERRY_PROP_SHOULD_THROW; + ecma_property_descriptor_t define_prop_desc = ecma_make_empty_define_property_descriptor (); - /* 8.a.i */ - ecma_value_t define_own_prop_ret = ecma_op_object_define_own_property (obj_p, property_name_p, &prop_desc); + if (ecma_property_descriptor_is_data_descriptor (&prop_desc)) + { + define_prop_desc.value = ecma_property_descriptor_value (&prop_desc); + } + else + { + define_prop_desc.u.accessor.get = ecma_property_descriptor_accessor_getter_value (&prop_desc); + define_prop_desc.u.accessor.set = ecma_property_descriptor_accessor_setter_value (&prop_desc); + } ecma_free_property_descriptor (&prop_desc); + define_prop_desc.flags |= (JERRY_PROP_SHOULD_THROW | JERRY_PROP_IS_CONFIGURABLE_DEFINED); + + /* 8.a.i */ + ecma_value_t define_own_prop_ret = + ecma_internal_method_define_own_property (obj_p, property_name_p, &define_prop_desc); + + ecma_free_define_property_descriptor (&define_prop_desc); + /* 8.a.ii */ if (ECMA_IS_VALUE_ERROR (define_own_prop_ret)) { @@ -397,36 +376,44 @@ ecma_builtin_object_set_integrity_level (ecma_object_t *obj_p, /**< object */ ecma_string_t *property_name_p = ecma_get_prop_name_from_value (buffer_p[i]); /* 9.1 */ - ecma_property_descriptor_t prop_desc; - ecma_value_t status = ecma_op_object_get_own_property_descriptor (obj_p, property_name_p, &prop_desc); + ecma_property_descriptor_t prop_desc = ecma_internal_method_get_own_property (obj_p, property_name_p); -#if JERRY_BUILTIN_PROXY - if (ECMA_IS_VALUE_ERROR (status)) + if (ecma_property_descriptor_error (&prop_desc)) { ecma_collection_free (props_p); + ecma_free_property_descriptor (&prop_desc); return ECMA_VALUE_ERROR; } -#endif /* JERRY_BUILTIN_PROXY */ - if (ecma_is_value_false (status)) + if (!ecma_property_descriptor_found (&prop_desc)) { + ecma_free_property_descriptor (&prop_desc); continue; } + ecma_property_descriptor_t define_prop_desc = ecma_make_empty_define_property_descriptor (); + /* 9.2 */ - if ((prop_desc.flags & (JERRY_PROP_IS_WRITABLE_DEFINED | JERRY_PROP_IS_WRITABLE)) - == (JERRY_PROP_IS_WRITABLE_DEFINED | JERRY_PROP_IS_WRITABLE)) + if (ecma_property_descriptor_is_data_descriptor (&prop_desc)) { - prop_desc.flags &= (uint16_t) ~JERRY_PROP_IS_WRITABLE; + prop_desc.value = ecma_property_descriptor_value (&prop_desc); + define_prop_desc.flags |= JERRY_PROP_IS_WRITABLE_DEFINED; } + else + { + define_prop_desc.u.accessor.get = ecma_property_descriptor_accessor_getter_value (&prop_desc); + define_prop_desc.u.accessor.set = ecma_property_descriptor_accessor_setter_value (&prop_desc); + } + + ecma_free_property_descriptor (&prop_desc); - prop_desc.flags &= (uint16_t) ~JERRY_PROP_IS_CONFIGURABLE; - prop_desc.flags |= JERRY_PROP_SHOULD_THROW; + define_prop_desc.flags |= (JERRY_PROP_SHOULD_THROW | JERRY_PROP_IS_CONFIGURABLE_DEFINED); /* 9.3 */ - ecma_value_t define_own_prop_ret = ecma_op_object_define_own_property (obj_p, property_name_p, &prop_desc); + ecma_value_t define_own_prop_ret = + ecma_internal_method_define_own_property (obj_p, property_name_p, &define_prop_desc); - ecma_free_property_descriptor (&prop_desc); + ecma_free_define_property_descriptor (&define_prop_desc); /* 9.4 */ if (ECMA_IS_VALUE_ERROR (define_own_prop_ret)) @@ -518,30 +505,22 @@ ecma_builtin_object_object_freeze (ecma_object_t *obj_p) /**< routine's argument ecma_value_t ecma_builtin_object_object_prevent_extensions (ecma_object_t *obj_p) /**< routine's argument */ { + ecma_value_t status = ecma_internal_method_prevent_extensions (obj_p); + #if JERRY_BUILTIN_PROXY - if (ECMA_OBJECT_IS_PROXY (obj_p)) + if (ECMA_IS_VALUE_ERROR (status)) { - ecma_value_t status = ecma_proxy_object_prevent_extensions (obj_p); - - if (ECMA_IS_VALUE_ERROR (status)) - { - return status; - } - - if (ecma_is_value_false (status)) - { - return ecma_raise_type_error (ECMA_ERR_SET_EXTENSIBLE_PROPERTY); - } - - JERRY_ASSERT (ecma_is_value_true (status)); + return status; } - else + + if (ecma_is_value_false (status)) { -#endif /* JERRY_BUILTIN_PROXY */ - ecma_op_ordinary_object_prevent_extensions (obj_p); -#if JERRY_BUILTIN_PROXY + return ecma_raise_type_error (ECMA_ERR_SET_EXTENSIBLE_PROPERTY); } #endif /* JERRY_BUILTIN_PROXY */ + + JERRY_ASSERT (ecma_is_value_true (status)); + ecma_ref_object (obj_p); return ecma_make_object_value (obj_p); @@ -564,26 +543,16 @@ ecma_builtin_object_test_integrity_level (ecma_object_t *obj_p, /**< routine's a JERRY_ASSERT (mode == ECMA_OBJECT_ROUTINE_IS_FROZEN || mode == ECMA_OBJECT_ROUTINE_IS_SEALED); /* 3. */ - bool is_extensible; + ecma_value_t is_extensible = ecma_internal_method_is_extensible (obj_p); + #if JERRY_BUILTIN_PROXY - if (ECMA_OBJECT_IS_PROXY (obj_p)) + if (ECMA_IS_VALUE_ERROR (is_extensible)) { - ecma_value_t status = ecma_proxy_object_is_extensible (obj_p); - - if (ECMA_IS_VALUE_ERROR (status)) - { - return status; - } - - is_extensible = ecma_is_value_true (status); + return is_extensible; } - else #endif /* JERRY_BUILTIN_PROXY */ - { - is_extensible = ecma_op_ordinary_object_is_extensible (obj_p); - } - if (is_extensible) + if (ecma_is_value_true (is_extensible)) { return ECMA_VALUE_FALSE; } @@ -592,7 +561,7 @@ ecma_builtin_object_test_integrity_level (ecma_object_t *obj_p, /**< routine's a ecma_value_t ret_value = ECMA_VALUE_TRUE; /* 2. */ - ecma_collection_t *props_p = ecma_op_object_own_property_keys (obj_p, JERRY_PROPERTY_FILTER_ALL); + ecma_collection_t *props_p = ecma_internal_method_own_property_keys (obj_p, JERRY_PROPERTY_FILTER_ALL); #if JERRY_BUILTIN_PROXY if (props_p == NULL) @@ -608,25 +577,26 @@ ecma_builtin_object_test_integrity_level (ecma_object_t *obj_p, /**< routine's a ecma_string_t *property_name_p = ecma_get_prop_name_from_value (buffer_p[i]); /* 2.a */ - ecma_property_descriptor_t prop_desc; - ecma_value_t status = ecma_op_object_get_own_property_descriptor (obj_p, property_name_p, &prop_desc); + ecma_property_descriptor_t prop_desc = ecma_internal_method_get_own_property (obj_p, property_name_p); #if JERRY_BUILTIN_PROXY - if (ECMA_IS_VALUE_ERROR (status)) + if (ecma_property_descriptor_error (&prop_desc)) { - ret_value = status; + ecma_free_property_descriptor (&prop_desc); + ret_value = ECMA_VALUE_ERROR; break; } #endif /* JERRY_BUILTIN_PROXY */ - if (ecma_is_value_false (status)) + if (!ecma_property_descriptor_found (&prop_desc)) { + ecma_free_property_descriptor (&prop_desc); continue; } - bool is_writable_data = ((prop_desc.flags & (JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_WRITABLE)) - == (JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_WRITABLE)); - bool is_configurable = (prop_desc.flags & JERRY_PROP_IS_CONFIGURABLE); + bool is_writable_data = + ecma_property_descriptor_is_data_descriptor (&prop_desc) && ecma_property_descriptor_is_writable (&prop_desc); + bool is_configurable = ecma_property_descriptor_is_configurable (&prop_desc); ecma_free_property_descriptor (&prop_desc); @@ -644,28 +614,6 @@ ecma_builtin_object_test_integrity_level (ecma_object_t *obj_p, /**< routine's a return ret_value; } /* ecma_builtin_object_test_integrity_level */ -/** - * The Object object's 'isExtensible' routine - * - * See also: - * ECMA-262 v5, 15.2.3.13 - * - * @return ecma value - * Returned value must be freed with ecma_free_value. - */ -ecma_value_t -ecma_builtin_object_object_is_extensible (ecma_object_t *obj_p) /**< routine's argument */ -{ -#if JERRY_BUILTIN_PROXY - if (ECMA_OBJECT_IS_PROXY (obj_p)) - { - return ecma_proxy_object_is_extensible (obj_p); - } -#endif /* JERRY_BUILTIN_PROXY */ - - return ecma_make_boolean_value (ecma_op_ordinary_object_is_extensible (obj_p)); -} /* ecma_builtin_object_object_is_extensible */ - /** * Common implementation of the Object object's 'keys', 'values', 'entries' routines * @@ -707,28 +655,28 @@ ecma_builtin_object_object_get_own_property_descriptor (ecma_object_t *obj_p, /* ecma_string_t *name_str_p) /**< routine's second argument */ { /* 3. */ - ecma_property_descriptor_t prop_desc; + ecma_property_descriptor_t prop_desc = ecma_internal_method_get_own_property (obj_p, name_str_p); - ecma_value_t status = ecma_op_object_get_own_property_descriptor (obj_p, name_str_p, &prop_desc); + ecma_value_t ret_value; -#if JERRY_BUILTIN_PROXY - if (ECMA_IS_VALUE_ERROR (status)) + if (ecma_property_descriptor_error (&prop_desc)) { - return status; + ret_value = ECMA_VALUE_ERROR; } -#endif /* JERRY_BUILTIN_PROXY */ - - if (ecma_is_value_true (status)) + else if (ecma_property_descriptor_found (&prop_desc)) { - /* 4. */ - ecma_object_t *desc_obj_p = ecma_op_from_property_descriptor (&prop_desc); + ecma_object_t *desc_obj_p = ecma_op_create_object_from_property_descriptor (&prop_desc); - ecma_free_property_descriptor (&prop_desc); - - return ecma_make_object_value (desc_obj_p); + ret_value = ecma_make_object_value (desc_obj_p); + } + else + { + ret_value = ECMA_VALUE_UNDEFINED; } - return ECMA_VALUE_UNDEFINED; + ecma_free_property_descriptor (&prop_desc); + + return ret_value; } /* ecma_builtin_object_object_get_own_property_descriptor */ #if JERRY_ESNEXT @@ -745,7 +693,7 @@ static ecma_value_t ecma_builtin_object_object_get_own_property_descriptors (ecma_object_t *obj_p) /**< routine's first argument */ { /* 2 */ - ecma_collection_t *prop_names_p = ecma_op_object_own_property_keys (obj_p, JERRY_PROPERTY_FILTER_ALL); + ecma_collection_t *prop_names_p = ecma_internal_method_own_property_keys (obj_p, JERRY_PROPERTY_FILTER_ALL); #if JERRY_BUILTIN_PROXY if (prop_names_p == NULL) @@ -766,23 +714,21 @@ ecma_builtin_object_object_get_own_property_descriptors (ecma_object_t *obj_p) / ecma_string_t *property_name_p = ecma_get_prop_name_from_value (names_buffer_p[i]); /* 4.a */ - ecma_property_descriptor_t prop_desc; - ecma_value_t status = ecma_op_object_get_own_property_descriptor (obj_p, property_name_p, &prop_desc); + ecma_property_descriptor_t prop_desc = ecma_internal_method_get_own_property (obj_p, property_name_p); -#if JERRY_BUILTIN_PROXY - if (ECMA_IS_VALUE_ERROR (status)) + if (ecma_property_descriptor_error (&prop_desc)) { ecma_deref_object (descriptors_p); ecma_collection_free (prop_names_p); + ecma_free_property_descriptor (&prop_desc); - return status; + return ECMA_VALUE_ERROR; } -#endif /* JERRY_BUILTIN_PROXY */ - if (ecma_is_value_true (status)) + if (ecma_property_descriptor_found (&prop_desc)) { /* 4.b */ - ecma_object_t *desc_obj_p = ecma_op_from_property_descriptor (&prop_desc); + ecma_object_t *desc_obj_p = ecma_op_create_object_from_property_descriptor (&prop_desc); /* 4.c */ ecma_property_value_t *value_p = ecma_create_named_data_property (descriptors_p, property_name_p, @@ -791,8 +737,9 @@ ecma_builtin_object_object_get_own_property_descriptors (ecma_object_t *obj_p) / value_p->value = ecma_make_object_value (desc_obj_p); ecma_deref_object (desc_obj_p); - ecma_free_property_descriptor (&prop_desc); } + + ecma_free_property_descriptor (&prop_desc); } ecma_collection_free (prop_names_p); @@ -826,7 +773,7 @@ ecma_builtin_object_object_define_properties (ecma_object_t *obj_p, /**< routine ecma_object_t *props_p = ecma_get_object_from_value (props); /* 3. */ - ecma_collection_t *prop_names_p = ecma_op_object_own_property_keys (props_p, JERRY_PROPERTY_FILTER_ALL); + ecma_collection_t *prop_names_p = ecma_internal_method_own_property_keys (props_p, JERRY_PROPERTY_FILTER_ALL); ecma_value_t ret_value = ECMA_VALUE_ERROR; #if JERRY_BUILTIN_PROXY @@ -849,21 +796,21 @@ ecma_builtin_object_object_define_properties (ecma_object_t *obj_p, /**< routine { ecma_string_t *prop_name_p = ecma_get_prop_name_from_value (buffer_p[i]); - ecma_property_descriptor_t prop_desc; - ecma_value_t get_desc = ecma_op_object_get_own_property_descriptor (props_p, prop_name_p, &prop_desc); + ecma_property_descriptor_t prop_desc = ecma_internal_method_get_own_property (props_p, prop_name_p); #if JERRY_ESNEXT - if (ECMA_IS_VALUE_ERROR (get_desc)) + if (ecma_property_descriptor_error (&prop_desc)) { + ecma_free_property_descriptor (&prop_desc); goto cleanup; } #endif /* JERRY_ESNEXT */ - if (ecma_is_value_true (get_desc)) + if (ecma_property_descriptor_found (&prop_desc)) { - if (prop_desc.flags & JERRY_PROP_IS_ENUMERABLE) + if (ecma_property_descriptor_is_enumerable (&prop_desc)) { - ecma_value_t desc_obj = ecma_op_object_get (props_p, prop_name_p); + ecma_value_t desc_obj = ecma_internal_method_get (props_p, prop_name_p, props); if (ECMA_IS_VALUE_ERROR (desc_obj)) { @@ -889,9 +836,9 @@ ecma_builtin_object_object_define_properties (ecma_object_t *obj_p, /**< routine ecma_ref_ecma_string (prop_name_p); ecma_collection_push_back (enum_prop_names, buffer_p[i]); } - - ecma_free_property_descriptor (&prop_desc); } + + ecma_free_property_descriptor (&prop_desc); } /* 6. */ @@ -900,7 +847,8 @@ ecma_builtin_object_object_define_properties (ecma_object_t *obj_p, /**< routine ecma_string_t *prop_name_p = ecma_get_prop_name_from_value (enum_prop_names->buffer_p[i]); ecma_value_t define_own_prop_ret = - ecma_op_object_define_own_property (obj_p, prop_name_p, &property_descriptors[i]); + ecma_internal_method_define_own_property (obj_p, prop_name_p, &property_descriptors[i]); + if (ECMA_IS_VALUE_ERROR (define_own_prop_ret)) { goto cleanup; @@ -916,7 +864,7 @@ ecma_builtin_object_object_define_properties (ecma_object_t *obj_p, /**< routine /* Clean up. */ for (uint32_t index = 0; index < property_descriptor_number; index++) { - ecma_free_property_descriptor (&property_descriptors[index]); + ecma_free_define_property_descriptor (&property_descriptors[index]); } ecma_collection_free (enum_prop_names); @@ -956,7 +904,7 @@ ecma_builtin_object_object_create (ecma_value_t arg1, /**< routine's first argum obj_p = ecma_get_object_from_value (arg1); } /* 2-3. */ - ecma_object_t *result_obj_p = ecma_op_create_object_object_noarg_and_set_prototype (obj_p); + ecma_object_t *result_obj_p = ecma_create_object (obj_p, 0, ECMA_OBJECT_TYPE_GENERAL); /* 4. */ if (!ecma_is_value_undefined (arg2)) @@ -1001,9 +949,9 @@ ecma_builtin_object_object_define_property (ecma_object_t *obj_p, /**< routine's prop_desc.flags |= JERRY_PROP_SHOULD_THROW; - ecma_value_t define_own_prop_ret = ecma_op_object_define_own_property (obj_p, name_str_p, &prop_desc); + ecma_value_t define_own_prop_ret = ecma_internal_method_define_own_property (obj_p, name_str_p, &prop_desc); - ecma_free_property_descriptor (&prop_desc); + ecma_free_define_property_descriptor (&prop_desc); ecma_free_value (conv_result); if (ECMA_IS_VALUE_ERROR (define_own_prop_ret)) @@ -1011,11 +959,6 @@ ecma_builtin_object_object_define_property (ecma_object_t *obj_p, /**< routine's return define_own_prop_ret; } - if (ecma_is_value_false (define_own_prop_ret)) - { - return ecma_raise_type_error (ECMA_ERR_THE_REQUESTED_PROPERTY_UPDATE_CANNOT_BE_PERFORMED); - } - JERRY_ASSERT (ecma_is_value_true (define_own_prop_ret)); ecma_ref_object (obj_p); @@ -1061,7 +1004,7 @@ ecma_builtin_object_object_assign (ecma_object_t *target_p, /**< target object * ecma_object_t *from_obj_p = ecma_get_object_from_value (from_value); /* 5.b.iii */ - ecma_collection_t *props_p = ecma_op_object_own_property_keys (from_obj_p, JERRY_PROPERTY_FILTER_ALL); + ecma_collection_t *props_p = ecma_internal_method_own_property_keys (from_obj_p, JERRY_PROPERTY_FILTER_ALL); #if JERRY_BUILTIN_PROXY if (props_p == NULL) @@ -1078,27 +1021,26 @@ ecma_builtin_object_object_assign (ecma_object_t *target_p, /**< target object * ecma_string_t *property_name_p = ecma_get_prop_name_from_value (buffer_p[j]); /* 5.c.i-ii */ - ecma_property_descriptor_t prop_desc; - ecma_value_t desc_status = ecma_op_object_get_own_property_descriptor (from_obj_p, property_name_p, &prop_desc); + ecma_property_descriptor_t prop_desc = ecma_internal_method_get_own_property (from_obj_p, property_name_p); -#if JERRY_BUILTIN_PROXY - if (ECMA_IS_VALUE_ERROR (desc_status)) + if (ecma_property_descriptor_error (&prop_desc)) { - ret_value = desc_status; + ecma_free_property_descriptor (&prop_desc); + ret_value = ECMA_VALUE_ERROR; break; } -#endif /* JERRY_BUILTIN_PROXY */ - if (ecma_is_value_false (desc_status)) + if (!ecma_property_descriptor_found (&prop_desc)) { + ecma_free_property_descriptor (&prop_desc); continue; } /* 5.c.iii */ - if (prop_desc.flags & JERRY_PROP_IS_ENUMERABLE) + if (ecma_property_descriptor_is_enumerable (&prop_desc)) { /* 5.c.iii.1 */ - ecma_value_t prop_value = ecma_op_object_get (from_obj_p, property_name_p); + ecma_value_t prop_value = ecma_internal_method_get (from_obj_p, property_name_p, from_value); /* 5.c.iii.2 */ if (ECMA_IS_VALUE_ERROR (prop_value)) @@ -1108,7 +1050,8 @@ ecma_builtin_object_object_assign (ecma_object_t *target_p, /**< target object * else { /* 5.c.iii.3 */ - ecma_value_t status = ecma_op_object_put (target_p, property_name_p, prop_value, true); + ecma_value_t status = + ecma_internal_method_set (target_p, property_name_p, prop_value, ecma_make_object_value (target_p), true); /* 5.c.iii.4 */ if (ECMA_IS_VALUE_ERROR (status)) @@ -1320,7 +1263,7 @@ ecma_op_object_get_own_property_keys (ecma_value_t this_arg, /**< this argument filter = (JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS | JERRY_PROPERTY_FILTER_EXCLUDE_INTEGER_INDICES); } - ecma_collection_t *props_p = ecma_op_object_own_property_keys (obj_p, filter); + ecma_collection_t *props_p = ecma_internal_method_own_property_keys (obj_p, filter); if (props_p == NULL) { @@ -1354,7 +1297,7 @@ ecma_op_object_get_own_property_keys (ecma_value_t this_arg, /**< this argument #else /* !JERRY_ESNEXT */ JERRY_UNUSED (type); ecma_object_t *obj_p = ecma_get_object_from_value (this_arg); - ecma_collection_t *props_p = ecma_op_object_own_property_keys (obj_p, JERRY_PROPERTY_FILTER_ALL); + ecma_collection_t *props_p = ecma_internal_method_own_property_keys (obj_p, JERRY_PROPERTY_FILTER_ALL); return ecma_op_new_array_object_from_collection (props_p, false); #endif /* JERRY_ESNEXT */ } /* ecma_op_object_get_own_property_keys */ @@ -1582,7 +1525,7 @@ ecma_builtin_object_dispatch_routine (uint8_t builtin_routine_id, /**< built-in } case ECMA_OBJECT_ROUTINE_IS_EXTENSIBLE: { - return ecma_builtin_object_object_is_extensible (obj_p); + return ecma_internal_method_is_extensible (obj_p); } default: { diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-object.h b/jerry-core/ecma/builtin-objects/ecma-builtin-object.h index f31b2617e7..ae93c58434 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-object.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-object.h @@ -25,8 +25,6 @@ ecma_value_t ecma_builtin_object_object_set_proto (ecma_value_t arg1, ecma_value ecma_value_t ecma_builtin_object_object_prevent_extensions (ecma_object_t *obj_p); -ecma_value_t ecma_builtin_object_object_is_extensible (ecma_object_t *obj_p); - ecma_value_t ecma_builtin_object_object_get_own_property_descriptor (ecma_object_t *obj_p, ecma_string_t *name_str_p); ecma_value_t ecma_builtin_object_object_define_property (ecma_object_t *obj_p, ecma_string_t *name_str_p, ecma_value_t arg3); diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-promise.c b/jerry-core/ecma/builtin-objects/ecma-builtin-promise.c index 7a53b9c10b..71bd623a0c 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-promise.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-promise.c @@ -22,6 +22,7 @@ #include "ecma-gc.h" #include "ecma-globals.h" #include "ecma-iterator-object.h" +#include "ecma-native-function.h" #include "ecma-number-object.h" #include "ecma-promise-object.h" @@ -134,7 +135,7 @@ ecma_builtin_promise_perform_race (ecma_value_t iterator, /**< the iterator for } /* h. */ - ecma_value_t next_promise = ecma_op_function_call (resolve_func_p, ctor, &next_val, 1); + ecma_value_t next_promise = ecma_internal_method_call (resolve_func_p, ctor, &next_val, 1); ecma_free_value (next_val); if (ECMA_IS_VALUE_ERROR (next_promise)) @@ -235,10 +236,10 @@ ecma_builtin_promise_perform (ecma_value_t iterator, /**< iteratorRecord */ } /* 2. */ - ecma_value_t resolve_result = ecma_op_function_call (ecma_get_object_from_value (capability_p->resolve), - ECMA_VALUE_UNDEFINED, - &values_array, - 1); + ecma_value_t resolve_result = ecma_internal_method_call (ecma_get_object_from_value (capability_p->resolve), + ECMA_VALUE_UNDEFINED, + &values_array, + 1); /* 3. */ if (ECMA_IS_VALUE_ERROR (resolve_result)) { @@ -270,7 +271,7 @@ ecma_builtin_promise_perform (ecma_value_t iterator, /**< iteratorRecord */ ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); /* i. */ - ecma_value_t next_promise = ecma_op_function_call (resolve_func_p, ctor, &next_value, 1); + ecma_value_t next_promise = ecma_internal_method_call (resolve_func_p, ctor, &next_value, 1); ecma_free_value (next_value); /* j. */ @@ -293,7 +294,7 @@ ecma_builtin_promise_perform (ecma_value_t iterator, /**< iteratorRecord */ { /* k. */ executor_func_p = - ecma_op_create_native_handler (ECMA_NATIVE_HANDLER_PROMISE_ALL_HELPER, sizeof (ecma_promise_all_executor_t)); + ecma_native_function_create (ECMA_NATIVE_HANDLER_PROMISE_ALL_HELPER, sizeof (ecma_promise_all_executor_t)); ecma_promise_all_executor_t *executor_p = (ecma_promise_all_executor_t *) executor_func_p; @@ -339,7 +340,7 @@ ecma_builtin_promise_perform (ecma_value_t iterator, /**< iteratorRecord */ } ecma_object_t *reject_func_p = - ecma_op_create_native_handler (ECMA_NATIVE_HANDLER_PROMISE_ALL_HELPER, sizeof (ecma_promise_all_executor_t)); + ecma_native_function_create (ECMA_NATIVE_HANDLER_PROMISE_ALL_HELPER, sizeof (ecma_promise_all_executor_t)); ecma_promise_all_executor_t *reject_p = (ecma_promise_all_executor_t *) reject_func_p; reject_p->index = idx; diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-reflect.c b/jerry-core/ecma/builtin-objects/ecma-builtin-reflect.c index 056a6b5f61..7f464b1854 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-reflect.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-reflect.c @@ -117,19 +117,19 @@ ecma_builtin_reflect_dispatch_routine (uint8_t builtin_routine_id, /**< built-in receiver = arguments_list[2]; } - ret_value = ecma_op_object_get_with_receiver (target_p, name_str_p, receiver); + ret_value = ecma_internal_method_get (target_p, name_str_p, receiver); break; } case ECMA_REFLECT_OBJECT_HAS: { - ret_value = ecma_op_object_has_property (target_p, name_str_p); + ret_value = ecma_internal_method_has_property (target_p, name_str_p); break; } case ECMA_REFLECT_OBJECT_DELETE_PROPERTY: { - ret_value = ecma_op_object_delete (target_p, name_str_p, false); + ret_value = ecma_internal_method_delete (target_p, name_str_p, false); break; } @@ -144,7 +144,7 @@ ecma_builtin_reflect_dispatch_routine (uint8_t builtin_routine_id, /**< built-in receiver = arguments_list[3]; } - ret_value = ecma_op_object_put_with_receiver (target_p, name_str_p, arguments_list[2], receiver, false); + ret_value = ecma_internal_method_set (target_p, name_str_p, arguments_list[2], receiver, false); break; } } @@ -164,7 +164,7 @@ ecma_builtin_reflect_dispatch_routine (uint8_t builtin_routine_id, /**< built-in ecma_object_t *target_p = ecma_get_object_from_value (arguments_list[0]); /* 2. */ - ecma_collection_t *prop_names = ecma_op_object_own_property_keys (target_p, JERRY_PROPERTY_FILTER_ALL); + ecma_collection_t *prop_names = ecma_internal_method_own_property_keys (target_p, JERRY_PROPERTY_FILTER_ALL); #if JERRY_BUILTIN_PROXY if (prop_names == NULL) @@ -214,7 +214,8 @@ ecma_builtin_reflect_dispatch_routine (uint8_t builtin_routine_id, /**< built-in return ECMA_VALUE_ERROR; } - ecma_value_t ret_value = ecma_op_function_construct (target_p, new_target_p, coll_p->buffer_p, coll_p->item_count); + ecma_value_t ret_value = + ecma_internal_method_construct (target_p, new_target_p, coll_p->buffer_p, coll_p->item_count); ecma_collection_free (coll_p); return ret_value; @@ -239,20 +240,7 @@ ecma_builtin_reflect_dispatch_routine (uint8_t builtin_routine_id, /**< built-in } ecma_object_t *obj_p = ecma_get_object_from_value (arguments_list[0]); - ecma_value_t status; - -#if JERRY_BUILTIN_PROXY - if (ECMA_OBJECT_IS_PROXY (obj_p)) - { - status = ecma_proxy_object_set_prototype_of (obj_p, arguments_list[1]); - } - else -#endif /* JERRY_BUILTIN_PROXY */ - { - status = ecma_op_ordinary_object_set_prototype_of (obj_p, arguments_list[1]); - } - - return status; + return ecma_internal_method_set_prototype_of (obj_p, arguments_list[1]); } case ECMA_REFLECT_OBJECT_APPLY: { @@ -283,10 +271,10 @@ ecma_builtin_reflect_dispatch_routine (uint8_t builtin_routine_id, /**< built-in return conv_result; } - ecma_value_t result = ecma_op_object_define_own_property (obj_p, name_str_p, &prop_desc); + ecma_value_t result = ecma_internal_method_define_own_property (obj_p, name_str_p, &prop_desc); ecma_deref_ecma_string (name_str_p); - ecma_free_property_descriptor (&prop_desc); + ecma_free_define_property_descriptor (&prop_desc); if (ECMA_IS_VALUE_ERROR (result)) { @@ -314,23 +302,13 @@ ecma_builtin_reflect_dispatch_routine (uint8_t builtin_routine_id, /**< built-in case ECMA_REFLECT_OBJECT_IS_EXTENSIBLE: { ecma_object_t *obj_p = ecma_get_object_from_value (arguments_list[0]); - return ecma_builtin_object_object_is_extensible (obj_p); + return ecma_internal_method_is_extensible (obj_p); } default: { JERRY_ASSERT (builtin_routine_id == ECMA_REFLECT_OBJECT_PREVENT_EXTENSIONS); ecma_object_t *obj_p = ecma_get_object_from_value (arguments_list[0]); - -#if JERRY_BUILTIN_PROXY - if (ECMA_OBJECT_IS_PROXY (obj_p)) - { - return ecma_proxy_object_prevent_extensions (obj_p); - } -#endif /* !JERRY_BUILTIN_PROXY */ - - ecma_op_ordinary_object_prevent_extensions (obj_p); - - return ECMA_VALUE_TRUE; + return ecma_internal_method_prevent_extensions (obj_p); } } } /* ecma_builtin_reflect_dispatch_routine */ diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-prototype.c b/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-prototype.c index 69fa1e47a8..f4993a77a1 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-prototype.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-prototype.c @@ -548,7 +548,7 @@ ecma_builtin_regexp_prototype_match_all (ecma_object_t *regexp_obj_p, /**< this ecma_object_t *constructor_obj_p = ecma_get_object_from_value (constructor); ecma_value_t flags_value = ecma_make_string_value (flags); ecma_value_t match_args[] = { ecma_make_object_value (regexp_obj_p), flags_value }; - ecma_value_t matcher = ecma_op_function_construct (constructor_obj_p, constructor_obj_p, match_args, 2); + ecma_value_t matcher = ecma_internal_method_construct (constructor_obj_p, constructor_obj_p, match_args, 2); ecma_deref_object (constructor_obj_p); @@ -586,8 +586,11 @@ ecma_builtin_regexp_prototype_match_all (ecma_object_t *regexp_obj_p, /**< this /* 8. */ ecma_object_t *matcher_obj_p = ecma_get_object_from_value (matcher); ecma_value_t last_index_value = ecma_make_length_value (last_index); - ecma_value_t set = - ecma_op_object_put (matcher_obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), last_index_value, true); + ecma_value_t set = ecma_internal_method_set (matcher_obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), + last_index_value, + ecma_make_object_value (matcher_obj_p), + true); ecma_free_value (last_index_value); diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-string-iterator-prototype.c b/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-string-iterator-prototype.c index 83070766ff..03bd3a08df 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-string-iterator-prototype.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-regexp-string-iterator-prototype.c @@ -148,10 +148,11 @@ ecma_builtin_regexp_string_iterator_prototype_object_next (ecma_value_t this_val ecma_op_advance_string_index (matcher_str_p, this_index, (flags & RE_FLAG_UNICODE) != 0); ecma_value_t next_index_value = ecma_make_length_value (next_index); - ecma_value_t set = ecma_op_object_put (regexp_obj_p, - ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), - next_index_value, - true); + ecma_value_t set = ecma_internal_method_set (regexp_obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), + next_index_value, + ecma_make_object_value (regexp_obj_p), + true); ecma_free_value (next_index_value); diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-string-iterator-prototype.c b/jerry-core/ecma/builtin-objects/ecma-builtin-string-iterator-prototype.c index c78082395a..47cdbf46b5 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-string-iterator-prototype.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-string-iterator-prototype.c @@ -100,7 +100,7 @@ ecma_builtin_string_iterator_prototype_object_next (ecma_value_t this_val) /**< /* After the ECMA_ITERATOR_INDEX_LIMIT limit is reached the [[%Iterator%NextIndex]] property is stored as an internal property */ ecma_string_t *prop_name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_ITERATOR_NEXT_INDEX); - ecma_value_t position_value = ecma_op_object_get (obj_p, prop_name_p); + ecma_value_t position_value = ecma_internal_method_get (obj_p, prop_name_p, this_val); position = (lit_utf8_size_t) (ecma_get_number_from_value (position_value)); ecma_free_value (position_value); @@ -157,8 +157,11 @@ ecma_builtin_string_iterator_prototype_object_next (ecma_value_t this_val) /**< ext_obj_p->u.cls.u2.iterator_index = ECMA_ITERATOR_INDEX_LIMIT; ecma_string_t *prop_name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_ITERATOR_NEXT_INDEX); - ecma_value_t put_result = - ecma_op_object_put (obj_p, prop_name_p, ecma_make_length_value (position + result_size), true); + ecma_value_t put_result = ecma_internal_method_set (obj_p, + prop_name_p, + ecma_make_length_value (position + result_size), + ecma_make_object_value (obj_p), + true); JERRY_ASSERT (ecma_is_value_true (put_result)); } diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.c b/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.c index fb46e02e99..9f2eea9fc5 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.c @@ -309,7 +309,7 @@ ecma_builtin_string_prototype_object_match (ecma_value_t this_argument, /**< thi { /* 3.c.i */ ecma_object_t *matcher_method = ecma_get_object_from_value (matcher); - ecma_value_t result = ecma_op_function_call (matcher_method, regexp_arg, &this_argument, 1); + ecma_value_t result = ecma_internal_method_call (matcher_method, regexp_arg, &this_argument, 1); ecma_deref_object (matcher_method); return result; } @@ -464,7 +464,7 @@ ecma_builtin_string_prototype_object_match_all (ecma_value_t this_argument, /**< { /* 2.d.i */ ecma_object_t *matcher_method = ecma_get_object_from_value (matcher); - ecma_value_t result = ecma_op_function_call (matcher_method, regexp_arg, &this_argument, 1); + ecma_value_t result = ecma_internal_method_call (matcher_method, regexp_arg, &this_argument, 1); ecma_deref_object (matcher_method); return result; } @@ -584,7 +584,7 @@ ecma_builtin_string_prototype_object_replace_helper (ecma_value_t this_value, /* if (!ecma_is_value_undefined (replace_symbol) && !ecma_is_value_null (replace_symbol)) { ecma_value_t arguments[] = { this_value, replace_value }; - ecma_value_t replace_result = ecma_op_function_validated_call (replace_symbol, search_value, arguments, 2); + ecma_value_t replace_result = ecma_internal_method_validated_call (replace_symbol, search_value, arguments, 2); ecma_free_value (replace_symbol); return replace_result; @@ -665,7 +665,7 @@ ecma_builtin_string_prototype_object_replace_helper (ecma_value_t this_value, /* ecma_make_uint32_value (pos), ecma_make_string_value (input_str_p) }; - result = ecma_op_function_call (function_p, ECMA_VALUE_UNDEFINED, args, 3); + result = ecma_internal_method_call (function_p, ECMA_VALUE_UNDEFINED, args, 3); if (ECMA_IS_VALUE_ERROR (result)) { @@ -776,7 +776,7 @@ ecma_builtin_string_prototype_object_search (ecma_value_t this_value, /**< this if (!ecma_is_value_undefined (search_symbol) && !ecma_is_value_null (search_symbol)) { - ecma_value_t search_result = ecma_op_function_validated_call (search_symbol, regexp_value, &this_value, 1); + ecma_value_t search_result = ecma_internal_method_validated_call (search_symbol, regexp_value, &this_value, 1); ecma_free_value (search_symbol); return search_result; } @@ -941,7 +941,7 @@ ecma_builtin_string_prototype_object_split (ecma_value_t this_value, /**< this a if (!ecma_is_value_undefined (split_symbol) && !ecma_is_value_null (split_symbol)) { ecma_value_t arguments[] = { this_value, limit_value }; - ecma_value_t split_result = ecma_op_function_validated_call (split_symbol, separator_value, arguments, 2); + ecma_value_t split_result = ecma_internal_method_validated_call (split_symbol, separator_value, arguments, 2); ecma_free_value (split_symbol); return split_result; diff --git a/jerry-core/ecma/builtin-objects/ecma-builtins.c b/jerry-core/ecma/builtin-objects/ecma-builtins.c index 61692cb048..fbd122882b 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtins.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtins.c @@ -23,6 +23,7 @@ #include "ecma-helpers-number.h" #include "ecma-helpers.h" #include "ecma-objects.h" +#include "ecma-ordinary-object.h" #include "jcontext.h" #include "jrt-bit-fields.h" @@ -361,7 +362,7 @@ ecma_instantiate_builtin (ecma_global_object_t *global_object_p, /**< global obj if (JERRY_UNLIKELY (obj_builtin_id == ECMA_BUILTIN_ID_TYPE_ERROR_THROWER)) { - ecma_op_ordinary_object_prevent_extensions (obj_p); + ecma_ordinary_object_prevent_extensions (obj_p); } else { @@ -735,21 +736,24 @@ ecma_builtin_make_function_object_for_setter_accessor (ecma_object_t *builtin_ob * @return pointer property, if one was instantiated, * NULL - otherwise. */ -static ecma_property_t * +static ecma_property_descriptor_t ecma_builtin_native_handler_try_to_instantiate_property (ecma_object_t *object_p, /**< object */ ecma_string_t *property_name_p) /**< property's name */ { + ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION); ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; - ecma_property_t *prop_p = NULL; if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_NAME)) { if ((ext_obj_p->u.built_in.u2.routine_flags & ECMA_NATIVE_HANDLER_FLAGS_NAME_INITIALIZED) == 0) { - ecma_property_value_t *value_p = - ecma_create_named_data_property (object_p, property_name_p, ECMA_PROPERTY_BUILT_IN_CONFIGURABLE, &prop_p); + prop_desc.flags = ECMA_PROP_DESC_PROPERTY_FOUND | ECMA_PROP_DESC_DATA_CONFIGURABLE; + ecma_property_value_t *value_p = ecma_create_named_data_property (object_p, + property_name_p, + ECMA_PROPERTY_BUILT_IN_CONFIGURABLE, + &prop_desc.u.property_p); value_p->value = ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); } @@ -758,15 +762,18 @@ ecma_builtin_native_handler_try_to_instantiate_property (ecma_object_t *object_p { if ((ext_obj_p->u.built_in.u2.routine_flags & ECMA_NATIVE_HANDLER_FLAGS_LENGTH_INITIALIZED) == 0) { - ecma_property_value_t *value_p = - ecma_create_named_data_property (object_p, property_name_p, ECMA_PROPERTY_BUILT_IN_CONFIGURABLE, &prop_p); + prop_desc.flags = ECMA_PROP_DESC_PROPERTY_FOUND | ECMA_PROP_DESC_DATA_CONFIGURABLE; + ecma_property_value_t *value_p = ecma_create_named_data_property (object_p, + property_name_p, + ECMA_PROPERTY_BUILT_IN_CONFIGURABLE, + &prop_desc.u.property_p); const uint8_t length = ecma_builtin_handler_get_length (ext_obj_p->u.built_in.routine_id); value_p->value = ecma_make_integer_value (length); } } - return prop_p; + return prop_desc; } /* ecma_builtin_native_handler_try_to_instantiate_property */ #endif /* JERRY_ESNEXT */ @@ -780,10 +787,12 @@ ecma_builtin_native_handler_try_to_instantiate_property (ecma_object_t *object_p * @return pointer property, if one was instantiated, * NULL - otherwise. */ -ecma_property_t * +static ecma_property_descriptor_t JERRY_ATTR_NOINLINE ecma_builtin_routine_try_to_instantiate_property (ecma_object_t *object_p, /**< object */ ecma_string_t *property_name_p) /**< property name */ { + ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); + JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION && ecma_builtin_function_is_routine (object_p)); @@ -801,26 +810,30 @@ ecma_builtin_routine_try_to_instantiate_property (ecma_object_t *object_p, /**< /* * Lazy instantiation of 'length' property */ - ecma_property_t *len_prop_p; - #if JERRY_ESNEXT uint8_t *bitset_p = &ext_func_p->u.built_in.u2.routine_flags; if (*bitset_p & ECMA_BUILTIN_ROUTINE_LENGTH_INITIALIZED) { /* length property was already instantiated */ - return NULL; + return prop_desc; } /* We mark that the property was lazily instantiated, * as it is configurable and so can be deleted (ECMA-262 v6, 19.2.4.1) */ - ecma_property_value_t *len_prop_value_p = - ecma_create_named_data_property (object_p, property_name_p, ECMA_PROPERTY_BUILT_IN_CONFIGURABLE, &len_prop_p); + prop_desc.flags = ECMA_PROP_DESC_PROPERTY_FOUND | ECMA_PROP_DESC_DATA_CONFIGURABLE; + ecma_property_value_t *len_prop_value_p = ecma_create_named_data_property (object_p, + property_name_p, + ECMA_PROPERTY_BUILT_IN_CONFIGURABLE, + &prop_desc.u.property_p); #else /* !JERRY_ESNEXT */ /* We don't need to mark that the property was already lazy instantiated, * as it is non-configurable and so can't be deleted (ECMA-262 v5, 13.2.5) */ - ecma_property_value_t *len_prop_value_p = - ecma_create_named_data_property (object_p, property_name_p, ECMA_PROPERTY_BUILT_IN_FIXED, &len_prop_p); + prop_desc.flags = ECMA_PROP_DESC_PROPERTY_FOUND | ECMA_PROP_DESC_DATA; + ecma_property_value_t *len_prop_value_p = ecma_create_named_data_property (object_p, + property_name_p, + ECMA_PROPERTY_BUILT_IN_FIXED, + &prop_desc.u.property_p); #endif /* JERRY_ESNEXT */ uint8_t length = 0; @@ -842,7 +855,7 @@ ecma_builtin_routine_try_to_instantiate_property (ecma_object_t *object_p, /**< } len_prop_value_p->value = ecma_make_integer_value (length); - return len_prop_p; + return prop_desc; } #if JERRY_ESNEXT @@ -856,13 +869,15 @@ ecma_builtin_routine_try_to_instantiate_property (ecma_object_t *object_p, /**< if (*bitset_p & ECMA_BUILTIN_ROUTINE_NAME_INITIALIZED) { /* name property was already instantiated */ - return NULL; + return prop_desc; } /* We mark that the property was lazily instantiated */ - ecma_property_t *name_prop_p; - ecma_property_value_t *name_prop_value_p = - ecma_create_named_data_property (object_p, property_name_p, ECMA_PROPERTY_BUILT_IN_CONFIGURABLE, &name_prop_p); + prop_desc.flags = ECMA_PROP_DESC_PROPERTY_FOUND | ECMA_PROP_DESC_DATA_CONFIGURABLE; + ecma_property_value_t *name_prop_value_p = ecma_create_named_data_property (object_p, + property_name_p, + ECMA_PROPERTY_BUILT_IN_CONFIGURABLE, + &prop_desc.u.property_p); uint8_t routine_index = ext_func_p->u.built_in.u.routine_index; const ecma_builtin_property_descriptor_t *property_list_p; @@ -916,11 +931,11 @@ ecma_builtin_routine_try_to_instantiate_property (ecma_object_t *object_p, /**< ecma_deref_ecma_string (name_p); } - return name_prop_p; + return prop_desc; } #endif /* JERRY_ESNEXT */ - return NULL; + return prop_desc; } /* ecma_builtin_routine_try_to_instantiate_property */ /** @@ -931,10 +946,12 @@ ecma_builtin_routine_try_to_instantiate_property (ecma_object_t *object_p, /**< * @return pointer property, if one was instantiated, * NULL - otherwise. */ -ecma_property_t * +static ecma_property_descriptor_t ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object */ ecma_string_t *property_name_p) /**< property's name */ { + ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); + lit_magic_string_id_t magic_string_id = ecma_get_string_magic (property_name_p); #if JERRY_ESNEXT @@ -946,7 +963,7 @@ ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object * if (magic_string_id == LIT_MAGIC_STRING__COUNT) { - return NULL; + return prop_desc; } ecma_built_in_props_t *built_in_props_p; @@ -976,7 +993,7 @@ ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object * { if (curr_property_p->magic_string_id == LIT_MAGIC_STRING__COUNT) { - return NULL; + return prop_desc; } curr_property_p++; } @@ -996,7 +1013,7 @@ ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object * if (*bitset_p & bit_for_index) { /* This property was instantiated before. */ - return NULL; + return prop_desc; } ecma_value_t value = ECMA_VALUE_EMPTY; @@ -1147,8 +1164,6 @@ ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object * } } - ecma_property_t *prop_p; - JERRY_ASSERT (curr_property_p->attributes & ECMA_PROPERTY_FLAG_BUILT_IN); if (is_accessor) @@ -1158,7 +1173,7 @@ ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object * getter_p, setter_p, curr_property_p->attributes, - &prop_p); + &prop_desc.u.property_p); if (setter_p) { @@ -1172,140 +1187,208 @@ ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object * else { ecma_property_value_t *prop_value_p = - ecma_create_named_data_property (object_p, property_name_p, curr_property_p->attributes, &prop_p); + ecma_create_named_data_property (object_p, property_name_p, curr_property_p->attributes, &prop_desc.u.property_p); prop_value_p->value = value; /* Reference count of objects must be decreased. */ ecma_deref_if_object (value); } - return prop_p; + prop_desc.flags = ECMA_PROP_DESC_PROPERTY_FOUND | ECMA_PROPERTY_TO_PROPERTY_DESCRIPTOR_FLAGS (prop_desc.u.property_p); + + return prop_desc; } /* ecma_builtin_try_to_instantiate_property */ -#if JERRY_ESNEXT +/* internal routines */ /** - * Delete configurable properties of native handlers. + * ecma built-in function object's [[GetOwnProperty]] internal method + * + * @return ecma property descriptor t */ -static void -ecma_builtin_native_handler_delete_built_in_property (ecma_object_t *object_p, /**< object */ - ecma_string_t *property_name_p) /**< property name */ +ecma_property_descriptor_t +ecma_builtin_function_object_get_own_property (ecma_object_t *obj_p, /**< the object */ + ecma_string_t *property_name_p) /**< property name */ { - ecma_extended_object_t *extended_obj_p = (ecma_extended_object_t *) object_p; + ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); - if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_LENGTH)) + prop_desc.u.property_p = ecma_find_named_property (obj_p, property_name_p); + + if (prop_desc.u.property_p == NULL) { - JERRY_ASSERT (!(extended_obj_p->u.built_in.u2.routine_flags & ECMA_NATIVE_HANDLER_FLAGS_LENGTH_INITIALIZED)); + if (ecma_builtin_function_is_routine (obj_p)) + { + return ecma_builtin_routine_try_to_instantiate_property (obj_p, property_name_p); + } - extended_obj_p->u.built_in.u2.routine_flags |= ECMA_NATIVE_HANDLER_FLAGS_LENGTH_INITIALIZED; - return; + return ecma_builtin_try_to_instantiate_property (obj_p, property_name_p); } - JERRY_ASSERT (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_NAME)); - JERRY_ASSERT (!(extended_obj_p->u.built_in.u2.routine_flags & ECMA_NATIVE_HANDLER_FLAGS_NAME_INITIALIZED)); - - extended_obj_p->u.built_in.u2.routine_flags |= ECMA_NATIVE_HANDLER_FLAGS_NAME_INITIALIZED; -} /* ecma_builtin_native_handler_delete_built_in_property */ + prop_desc.flags = ECMA_PROP_DESC_PROPERTY_FOUND | ECMA_PROPERTY_TO_PROPERTY_DESCRIPTOR_FLAGS (prop_desc.u.property_p); + return prop_desc; +} /* ecma_builtin_function_object_get_own_property */ /** - * Delete configurable properties of built-in routines. + * ecma built-in object's [[GetOwnProperty]] internal method + * + * @return ecma property descriptor t */ -void -ecma_builtin_routine_delete_built_in_property (ecma_object_t *object_p, /**< object */ - ecma_string_t *property_name_p) /**< property name */ +ecma_property_descriptor_t +ecma_builtin_object_get_own_property (ecma_object_t *obj_p, /**< the object */ + ecma_string_t *property_name_p) /**< property name */ { - JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION - && ecma_builtin_function_is_routine (object_p)); + ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); - ecma_extended_object_t *extended_obj_p = (ecma_extended_object_t *) object_p; + prop_desc.u.property_p = ecma_find_named_property (obj_p, property_name_p); - if (JERRY_UNLIKELY (extended_obj_p->u.built_in.id == ECMA_BUILTIN_ID_HANDLER)) + if (prop_desc.u.property_p == NULL) { - ecma_builtin_native_handler_delete_built_in_property (object_p, property_name_p); - return; + return ecma_builtin_try_to_instantiate_property (obj_p, property_name_p); } - uint8_t *bitset_p = &extended_obj_p->u.built_in.u2.routine_flags; + prop_desc.flags = ECMA_PROP_DESC_PROPERTY_FOUND | ECMA_PROPERTY_TO_PROPERTY_DESCRIPTOR_FLAGS (prop_desc.u.property_p); + return prop_desc; +} /* ecma_builtin_object_get_own_property */ - if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_LENGTH)) - { - JERRY_ASSERT (!(*bitset_p & ECMA_BUILTIN_ROUTINE_LENGTH_INITIALIZED)); +/** + * Handle calling [[Call]] of built-in function object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_function_object_call (ecma_object_t *obj_p, /**< built-in object */ + ecma_value_t this_arg_value, /**< 'this' argument value */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< arguments list length */ +{ + JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION); - *bitset_p |= ECMA_BUILTIN_ROUTINE_LENGTH_INITIALIZED; - return; - } + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; - JERRY_ASSERT (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_NAME)); - JERRY_ASSERT (!(*bitset_p & ECMA_BUILTIN_ROUTINE_NAME_INITIALIZED)); +#if JERRY_BUILTIN_REALMS + ecma_global_object_t *saved_global_object_p = JERRY_CONTEXT (global_object_p); - *bitset_p |= ECMA_BUILTIN_ROUTINE_NAME_INITIALIZED; -} /* ecma_builtin_routine_delete_built_in_property */ + ecma_extended_object_t *ext_func_obj_p = (ecma_extended_object_t *) obj_p; + JERRY_CONTEXT (global_object_p) = + ECMA_GET_INTERNAL_VALUE_POINTER (ecma_global_object_t, ext_func_obj_p->u.built_in.realm_value); +#endif /* JERRY_BUILTIN_REALMS */ + +#if JERRY_ESNEXT + ecma_object_t *old_new_target_p = JERRY_CONTEXT (current_new_target_p); + if (JERRY_UNLIKELY (!(JERRY_CONTEXT (status_flags) & ECMA_STATUS_DIRECT_EVAL))) + { + JERRY_CONTEXT (current_new_target_p) = NULL; + } #endif /* JERRY_ESNEXT */ -/** - * Delete configurable properties of built-ins. - */ -void -ecma_builtin_delete_built_in_property (ecma_object_t *object_p, /**< object */ - ecma_string_t *property_name_p) /**< property name */ -{ - lit_magic_string_id_t magic_string_id = ecma_get_string_magic (property_name_p); + ecma_value_t result; -#if JERRY_ESNEXT - if (JERRY_UNLIKELY (ecma_prop_name_is_symbol (property_name_p))) + if (ecma_builtin_function_is_routine (obj_p)) { - if (property_name_p->u.hash & ECMA_SYMBOL_FLAG_GLOBAL) +#if JERRY_ESNEXT + if (JERRY_UNLIKELY (ext_obj_p->u.built_in.id == ECMA_BUILTIN_ID_HANDLER)) { - magic_string_id = (property_name_p->u.hash >> ECMA_SYMBOL_FLAGS_SHIFT); + ecma_builtin_handler_t handler = ecma_builtin_handler_get (ext_obj_p->u.built_in.routine_id); + result = handler (obj_p, arguments_list_p, arguments_list_len); } - } -#endif /* JERRY_ESNEXT */ + else +#endif /* !JERRY_ESNEXT */ + { + ecma_value_t padded_arguments_list_p[3] = { ECMA_VALUE_UNDEFINED, ECMA_VALUE_UNDEFINED, ECMA_VALUE_UNDEFINED }; - ecma_built_in_props_t *built_in_props_p; - ecma_object_type_t object_type = ecma_get_object_type (object_p); + if (arguments_list_len <= 2) + { + switch (arguments_list_len) + { + case 2: + { + padded_arguments_list_p[1] = arguments_list_p[1]; + /* FALLTHRU */ + } + case 1: + { + padded_arguments_list_p[0] = arguments_list_p[0]; + break; + } + default: + { + JERRY_ASSERT (arguments_list_len == 0); + } + } - JERRY_ASSERT (object_type == ECMA_OBJECT_TYPE_BUILT_IN_GENERAL || object_type == ECMA_OBJECT_TYPE_BUILT_IN_CLASS - || object_type == ECMA_OBJECT_TYPE_BUILT_IN_ARRAY - || (object_type == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION && !ecma_builtin_function_is_routine (object_p))); + arguments_list_p = padded_arguments_list_p; + } - if (ECMA_BUILTIN_IS_EXTENDED_BUILT_IN (object_type)) - { - built_in_props_p = &((ecma_extended_built_in_object_t *) object_p)->built_in; + result = ecma_builtin_routines[ext_obj_p->u.built_in.id](ext_obj_p->u.built_in.routine_id, + this_arg_value, + arguments_list_p, + arguments_list_len); + } } else { - built_in_props_p = &((ecma_extended_object_t *) object_p)->u.built_in; + ecma_builtin_id_t builtin_object_id = ext_obj_p->u.built_in.id; + JERRY_ASSERT (builtin_object_id < sizeof (ecma_builtin_call_functions) / sizeof (ecma_builtin_dispatch_call_t)); + result = ecma_builtin_call_functions[builtin_object_id](arguments_list_p, arguments_list_len); } - ecma_builtin_id_t builtin_id = (ecma_builtin_id_t) built_in_props_p->id; +#if JERRY_ESNEXT + JERRY_CONTEXT (current_new_target_p) = old_new_target_p; +#endif /* JERRY_ESNEXT */ - JERRY_ASSERT (builtin_id < ECMA_BUILTIN_ID__COUNT); +#if JERRY_BUILTIN_REALMS + JERRY_CONTEXT (global_object_p) = saved_global_object_p; +#endif /* JERRY_BUILTIN_REALMS */ - const ecma_builtin_property_descriptor_t *property_list_p = ecma_builtin_property_list_references[builtin_id]; - const ecma_builtin_property_descriptor_t *curr_property_p = property_list_p; + return result; +} /* ecma_builtin_function_object_call */ - while (curr_property_p->magic_string_id != magic_string_id) +/** + * Handle calling [[Construct]] of built-in function object + * + * @return ecma value + */ +ecma_value_t +ecma_builtin_function_object_construct (ecma_object_t *obj_p, /**< built-in object */ + ecma_object_t *new_target_p, /**< built-in object */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< arguments list length */ +{ + JERRY_UNUSED (new_target_p); + + if (ecma_builtin_function_is_routine (obj_p)) { - JERRY_ASSERT (curr_property_p->magic_string_id != LIT_MAGIC_STRING__COUNT); - curr_property_p++; + return ecma_raise_type_error (ECMA_ERR_BULTIN_ROUTINES_HAVE_NO_CONSTRUCTOR); } - uint32_t index = (uint32_t) (curr_property_p - property_list_p); - uint8_t *bitset_p = built_in_props_p->u2.instantiated_bitset + (index >> 3); - #if JERRY_BUILTIN_REALMS - if (index >= 8 * sizeof (uint8_t)) - { - bitset_p += sizeof (ecma_value_t); - } + ecma_global_object_t *saved_global_object_p = JERRY_CONTEXT (global_object_p); + ecma_value_t realm_value = ((ecma_extended_object_t *) obj_p)->u.built_in.realm_value; + JERRY_CONTEXT (global_object_p) = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_global_object_t, realm_value); #endif /* JERRY_BUILTIN_REALMS */ - uint8_t bit_for_index = (uint8_t) (1u << (index & 0x7)); - JERRY_ASSERT (!(*bitset_p & bit_for_index)); +#if JERRY_ESNEXT + ecma_object_t *old_new_target = JERRY_CONTEXT (current_new_target_p); + JERRY_CONTEXT (current_new_target_p) = new_target_p; +#endif /* JERRY_ESNEXT */ - *bitset_p |= bit_for_index; -} /* ecma_builtin_delete_built_in_property */ + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + ecma_builtin_id_t builtin_object_id = ext_obj_p->u.built_in.id; + JERRY_ASSERT (builtin_object_id < sizeof (ecma_builtin_construct_functions) / sizeof (ecma_builtin_dispatch_call_t)); + + ecma_value_t result = ecma_builtin_construct_functions[builtin_object_id](arguments_list_p, arguments_list_len); + +#if JERRY_ESNEXT + JERRY_CONTEXT (current_new_target_p) = old_new_target; +#endif /* JERRY_ESNEXT */ + +#if JERRY_BUILTIN_REALMS + JERRY_CONTEXT (global_object_p) = saved_global_object_p; +#endif /* JERRY_BUILTIN_REALMS */ + + return result; +} /* ecma_builtin_function_object_construct */ #if JERRY_ESNEXT @@ -1314,9 +1397,9 @@ ecma_builtin_delete_built_in_property (ecma_object_t *object_p, /**< object */ * adding them to corresponding string collections */ static void -ecma_builtin_native_handler_list_lazy_property_names (ecma_object_t *object_p, /**< function object */ - ecma_collection_t *prop_names_p, /**< prop name collection */ - ecma_property_counter_t *prop_counter_p) /**< prop counter */ +ecma_builtin_native_handler_list_lazy_property_keys (ecma_object_t *object_p, /**< function object */ + ecma_collection_t *prop_names_p, /**< prop name collection */ + ecma_property_counter_t *prop_counter_p) /**< prop counter */ { JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION); ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; @@ -1332,21 +1415,18 @@ ecma_builtin_native_handler_list_lazy_property_names (ecma_object_t *object_p, / ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); prop_counter_p->string_named_props++; } -} /* ecma_builtin_native_handler_list_lazy_property_names */ +} /* ecma_builtin_native_handler_list_lazy_property_keys */ #endif /* JERRY_ESNEXT */ /** * List names of a built-in function's lazy instantiated properties - * - * See also: - * ecma_builtin_routine_try_to_instantiate_property */ -void -ecma_builtin_routine_list_lazy_property_names (ecma_object_t *object_p, /**< a built-in object */ - ecma_collection_t *prop_names_p, /**< prop name collection */ - ecma_property_counter_t *prop_counter_p, /**< property counters */ - jerry_property_filter_t filter) /**< name filters */ +static void +ecma_builtin_routine_list_lazy_property_keys (ecma_object_t *object_p, /**< a built-in object */ + ecma_collection_t *prop_names_p, /**< prop name collection */ + ecma_property_counter_t *prop_counter_p, /**< property counters */ + jerry_property_filter_t filter) /**< name filters */ { JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION); JERRY_ASSERT (ecma_builtin_function_is_routine (object_p)); @@ -1361,7 +1441,7 @@ ecma_builtin_routine_list_lazy_property_names (ecma_object_t *object_p, /**< a b if (JERRY_UNLIKELY (ext_func_p->u.built_in.id == ECMA_BUILTIN_ID_HANDLER)) { - ecma_builtin_native_handler_list_lazy_property_names (object_p, prop_names_p, prop_counter_p); + ecma_builtin_native_handler_list_lazy_property_keys (object_p, prop_names_p, prop_counter_p); return; } @@ -1382,7 +1462,7 @@ ecma_builtin_routine_list_lazy_property_names (ecma_object_t *object_p, /**< a b ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); prop_counter_p->string_named_props++; #endif /* JERRY_ESNEXT */ -} /* ecma_builtin_routine_list_lazy_property_names */ +} /* ecma_builtin_routine_list_lazy_property_keys */ /** * List names of a built-in object's lazy instantiated properties @@ -1391,10 +1471,10 @@ ecma_builtin_routine_list_lazy_property_names (ecma_object_t *object_p, /**< a b * ecma_builtin_try_to_instantiate_property */ void -ecma_builtin_list_lazy_property_names (ecma_object_t *object_p, /**< a built-in object */ - ecma_collection_t *prop_names_p, /**< prop name collection */ - ecma_property_counter_t *prop_counter_p, /**< property counters */ - jerry_property_filter_t filter) /**< name filters */ +ecma_builtin_object_list_lazy_property_keys (ecma_object_t *object_p, /**< a built-in object */ + ecma_collection_t *prop_names_p, /**< prop name collection */ + ecma_property_counter_t *prop_counter_p, /**< property counters */ + jerry_property_filter_t filter) /**< name filters */ { JERRY_ASSERT (ecma_get_object_type (object_p) != ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION || !ecma_builtin_function_is_routine (object_p)); @@ -1499,109 +1579,167 @@ ecma_builtin_list_lazy_property_names (ecma_object_t *object_p, /**< a built-in } } #endif /* JERRY_ESNEXT */ -} /* ecma_builtin_list_lazy_property_names */ +} /* ecma_builtin_object_list_lazy_property_keys */ /** - * Dispatcher of built-in routines - * - * @return ecma value - * Returned value must be freed with ecma_free_value. + * List names of a built-in function object's lazy instantiated properties */ -static ecma_value_t -ecma_builtin_dispatch_routine (ecma_extended_object_t *func_obj_p, /**< builtin object */ - ecma_value_t this_arg_value, /**< 'this' argument value */ - const ecma_value_t *arguments_list_p, /**< list of arguments passed to routine */ - uint32_t arguments_list_len) /**< length of arguments' list */ +void +ecma_builtin_function_list_lazy_property_keys (ecma_object_t *object_p, /**< a built-in object */ + ecma_collection_t *prop_names_p, /**< prop name collection */ + ecma_property_counter_t *prop_counter_p, /**< property counters */ + jerry_property_filter_t filter) /**< name filters */ { - JERRY_ASSERT (ecma_builtin_function_is_routine ((ecma_object_t *) func_obj_p)); + if (ecma_builtin_function_is_routine (object_p)) + { + ecma_builtin_routine_list_lazy_property_keys (object_p, prop_names_p, prop_counter_p, filter); + return; + } - ecma_value_t padded_arguments_list_p[3] = { ECMA_VALUE_UNDEFINED, ECMA_VALUE_UNDEFINED, ECMA_VALUE_UNDEFINED }; + ecma_builtin_object_list_lazy_property_keys (object_p, prop_names_p, prop_counter_p, filter); +} /* ecma_builtin_function_list_lazy_property_keys */ + +#if JERRY_ESNEXT +/** + * Delete configurable properties of native handlers. + */ +static void +ecma_builtin_native_handler_delete_lazy_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *property_name_p) /**< property name */ +{ + ecma_extended_object_t *extended_obj_p = (ecma_extended_object_t *) object_p; - if (arguments_list_len <= 2) + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_LENGTH)) { - switch (arguments_list_len) - { - case 2: - { - padded_arguments_list_p[1] = arguments_list_p[1]; - /* FALLTHRU */ - } - case 1: - { - padded_arguments_list_p[0] = arguments_list_p[0]; - break; - } - default: - { - JERRY_ASSERT (arguments_list_len == 0); - } - } + JERRY_ASSERT (!(extended_obj_p->u.built_in.u2.routine_flags & ECMA_NATIVE_HANDLER_FLAGS_LENGTH_INITIALIZED)); - arguments_list_p = padded_arguments_list_p; + extended_obj_p->u.built_in.u2.routine_flags |= ECMA_NATIVE_HANDLER_FLAGS_LENGTH_INITIALIZED; + return; } - return ecma_builtin_routines[func_obj_p->u.built_in.id](func_obj_p->u.built_in.routine_id, - this_arg_value, - arguments_list_p, - arguments_list_len); -} /* ecma_builtin_dispatch_routine */ + JERRY_ASSERT (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_NAME)); + JERRY_ASSERT (!(extended_obj_p->u.built_in.u2.routine_flags & ECMA_NATIVE_HANDLER_FLAGS_NAME_INITIALIZED)); + + extended_obj_p->u.built_in.u2.routine_flags |= ECMA_NATIVE_HANDLER_FLAGS_NAME_INITIALIZED; +} /* ecma_builtin_native_handler_delete_lazy_property */ /** - * Handle calling [[Call]] of built-in object - * - * @return ecma value + * Delete configurable properties of built-in routines. */ -ecma_value_t -ecma_builtin_dispatch_call (ecma_object_t *obj_p, /**< built-in object */ - ecma_value_t this_arg_value, /**< 'this' argument value */ - const ecma_value_t *arguments_list_p, /**< arguments list */ - uint32_t arguments_list_len) /**< arguments list length */ +static void +ecma_builtin_routine_delete_lazy_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *property_name_p) /**< property name */ { - JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION); + JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION + && ecma_builtin_function_is_routine (object_p)); - ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; + ecma_extended_object_t *extended_obj_p = (ecma_extended_object_t *) object_p; - if (ecma_builtin_function_is_routine (obj_p)) + if (JERRY_UNLIKELY (extended_obj_p->u.built_in.id == ECMA_BUILTIN_ID_HANDLER)) + { + ecma_builtin_native_handler_delete_lazy_property (object_p, property_name_p); + return; + } + + uint8_t *bitset_p = &extended_obj_p->u.built_in.u2.routine_flags; + + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_LENGTH)) + { + JERRY_ASSERT (!(*bitset_p & ECMA_BUILTIN_ROUTINE_LENGTH_INITIALIZED)); + + *bitset_p |= ECMA_BUILTIN_ROUTINE_LENGTH_INITIALIZED; + return; + } + + JERRY_ASSERT (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_NAME)); + JERRY_ASSERT (!(*bitset_p & ECMA_BUILTIN_ROUTINE_NAME_INITIALIZED)); + + *bitset_p |= ECMA_BUILTIN_ROUTINE_NAME_INITIALIZED; +} /* ecma_builtin_routine_delete_lazy_property */ + +#endif /* JERRY_ESNEXT */ + +/** + * Delete configurable properties of built-ins. + */ +void +ecma_builtin_object_delete_lazy_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *property_name_p) /**< property name */ +{ + ecma_built_in_props_t *built_in_props_p; + ecma_object_type_t object_type = ecma_get_object_type (object_p); + + JERRY_ASSERT (object_type == ECMA_OBJECT_TYPE_BUILT_IN_GENERAL || object_type == ECMA_OBJECT_TYPE_BUILT_IN_CLASS + || object_type == ECMA_OBJECT_TYPE_BUILT_IN_ARRAY + || (object_type == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION && !ecma_builtin_function_is_routine (object_p))); + + if (ECMA_BUILTIN_IS_EXTENDED_BUILT_IN (object_type)) { + built_in_props_p = &((ecma_extended_built_in_object_t *) object_p)->built_in; + } + else + { + built_in_props_p = &((ecma_extended_object_t *) object_p)->u.built_in; + } + + ecma_builtin_id_t builtin_id = (ecma_builtin_id_t) built_in_props_p->id; + + JERRY_ASSERT (builtin_id < ECMA_BUILTIN_ID__COUNT); + + const ecma_builtin_property_descriptor_t *property_list_p = ecma_builtin_property_list_references[builtin_id]; + const ecma_builtin_property_descriptor_t *curr_property_p = property_list_p; + + lit_magic_string_id_t magic_string_id = ecma_get_string_magic (property_name_p); + #if JERRY_ESNEXT - if (JERRY_UNLIKELY (ext_obj_p->u.built_in.id == ECMA_BUILTIN_ID_HANDLER)) + if (JERRY_UNLIKELY (ecma_prop_name_is_symbol (property_name_p))) + { + if (property_name_p->u.hash & ECMA_SYMBOL_FLAG_GLOBAL) { - ecma_builtin_handler_t handler = ecma_builtin_handler_get (ext_obj_p->u.built_in.routine_id); - return handler (obj_p, arguments_list_p, arguments_list_len); + magic_string_id = (property_name_p->u.hash >> ECMA_SYMBOL_FLAGS_SHIFT); } -#endif /* !JERRY_ESNEXT */ + } +#endif /* JERRY_ESNEXT */ - return ecma_builtin_dispatch_routine (ext_obj_p, this_arg_value, arguments_list_p, arguments_list_len); + while (curr_property_p->magic_string_id != magic_string_id) + { + JERRY_ASSERT (curr_property_p->magic_string_id != LIT_MAGIC_STRING__COUNT); + curr_property_p++; } - ecma_builtin_id_t builtin_object_id = ext_obj_p->u.built_in.id; - JERRY_ASSERT (builtin_object_id < sizeof (ecma_builtin_call_functions) / sizeof (ecma_builtin_dispatch_call_t)); - return ecma_builtin_call_functions[builtin_object_id](arguments_list_p, arguments_list_len); -} /* ecma_builtin_dispatch_call */ + uint32_t index = (uint32_t) (curr_property_p - property_list_p); + uint8_t *bitset_p = built_in_props_p->u2.instantiated_bitset + (index >> 3); + +#if JERRY_BUILTIN_REALMS + if (index >= 8 * sizeof (uint8_t)) + { + bitset_p += sizeof (ecma_value_t); + } +#endif /* JERRY_BUILTIN_REALMS */ + + uint8_t bit_for_index = (uint8_t) (1u << (index & 0x7)); + JERRY_ASSERT (!(*bitset_p & bit_for_index)); + + *bitset_p |= bit_for_index; +} /* ecma_builtin_object_delete_lazy_property */ /** - * Handle calling [[Construct]] of built-in object - * - * @return ecma value + * Delete configurable properties of built-in functions. */ -ecma_value_t -ecma_builtin_dispatch_construct (ecma_object_t *obj_p, /**< built-in object */ - const ecma_value_t *arguments_list_p, /**< arguments list */ - uint32_t arguments_list_len) /**< arguments list length */ +void +ecma_builtin_function_delete_lazy_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *property_name_p) /**< property name */ { - JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION); - - if (ecma_builtin_function_is_routine (obj_p)) +#if JERRY_ESNEXT + if (ecma_builtin_function_is_routine (object_p)) { - return ecma_raise_type_error (ECMA_ERR_BULTIN_ROUTINES_HAVE_NO_CONSTRUCTOR); + ecma_builtin_routine_delete_lazy_property (object_p, property_name_p); + return; } +#endif /* JERRY_ESNEXT */ - ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; - ecma_builtin_id_t builtin_object_id = ext_obj_p->u.built_in.id; - JERRY_ASSERT (builtin_object_id < sizeof (ecma_builtin_construct_functions) / sizeof (ecma_builtin_dispatch_call_t)); - - return ecma_builtin_construct_functions[builtin_object_id](arguments_list_p, arguments_list_len); -} /* ecma_builtin_dispatch_construct */ + ecma_builtin_object_delete_lazy_property (object_p, property_name_p); +} /* ecma_builtin_function_delete_lazy_property */ /** * @} diff --git a/jerry-core/ecma/builtin-objects/ecma-builtins.h b/jerry-core/ecma/builtin-objects/ecma-builtins.h index 96040de7ff..0057c15a84 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtins.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtins.h @@ -110,28 +110,6 @@ typedef struct ecma_global_object_t *ecma_builtin_create_global_object (void); -ecma_value_t ecma_builtin_dispatch_call (ecma_object_t *obj_p, - ecma_value_t this_arg_value, - const ecma_value_t *arguments_list_p, - uint32_t arguments_list_len); -ecma_value_t ecma_builtin_dispatch_construct (ecma_object_t *obj_p, - const ecma_value_t *arguments_list_p, - uint32_t arguments_list_len); -ecma_property_t *ecma_builtin_routine_try_to_instantiate_property (ecma_object_t *object_p, - ecma_string_t *property_name_p); -ecma_property_t *ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, ecma_string_t *property_name_p); -#if JERRY_ESNEXT -void ecma_builtin_routine_delete_built_in_property (ecma_object_t *object_p, ecma_string_t *property_name_p); -#endif /* JERRY_ESNEXT */ -void ecma_builtin_delete_built_in_property (ecma_object_t *object_p, ecma_string_t *property_name_p); -void ecma_builtin_routine_list_lazy_property_names (ecma_object_t *object_p, - ecma_collection_t *prop_names_p, - ecma_property_counter_t *prop_counter_p, - jerry_property_filter_t filter); -void ecma_builtin_list_lazy_property_names (ecma_object_t *object_p, - ecma_collection_t *prop_names_p, - ecma_property_counter_t *prop_counter_p, - jerry_property_filter_t filter); bool ecma_builtin_is_global (ecma_object_t *object_p); ecma_object_t *ecma_builtin_get (ecma_builtin_id_t builtin_id); ecma_object_t *ecma_builtin_get_global (void); @@ -141,4 +119,89 @@ bool ecma_builtin_function_is_routine (ecma_object_t *func_obj_p); ecma_object_t *ecma_builtin_get_from_realm (ecma_global_object_t *global_object_p, ecma_builtin_id_t builtin_id); #endif /* JERRY_BUILTIN_REALMS */ +ecma_property_descriptor_t ecma_builtin_function_object_get_own_property (ecma_object_t *obj_p, + ecma_string_t *property_name_p); + +ecma_value_t ecma_builtin_function_object_call (ecma_object_t *obj_p, + ecma_value_t this_arg_value, + const ecma_value_t *arguments_list_p, + uint32_t arguments_list_len); +ecma_value_t ecma_builtin_function_object_construct (ecma_object_t *obj_p, + ecma_object_t *new_target_p, + const ecma_value_t *arguments_list_p, + uint32_t arguments_list_len); +void ecma_builtin_function_list_lazy_property_keys (ecma_object_t *object_p, + ecma_collection_t *prop_names_p, + ecma_property_counter_t *prop_counter_p, + jerry_property_filter_t filter); +void ecma_builtin_function_delete_lazy_property (ecma_object_t *object_p, ecma_string_t *property_name_p); + +/** + * Virtual function table for built-in function object's internal methods + */ +#define ECMA_BUILT_IN_FUNCTION_OBJ_VTABLE \ + [ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION] = { ecma_ordinary_object_get_prototype_of, \ + ecma_ordinary_object_set_prototype_of, \ + ecma_ordinary_object_is_extensible, \ + ecma_ordinary_object_prevent_extensions, \ + ecma_builtin_function_object_get_own_property, \ + ecma_ordinary_object_define_own_property, \ + ecma_ordinary_object_has_property, \ + ecma_ordinary_object_get, \ + ecma_ordinary_object_set, \ + ecma_ordinary_object_delete, \ + ecma_ordinary_object_own_property_keys, \ + ecma_builtin_function_object_call, \ + ecma_builtin_function_object_construct, \ + ecma_builtin_function_list_lazy_property_keys, \ + ecma_builtin_function_delete_lazy_property } + +ecma_property_descriptor_t ecma_builtin_object_get_own_property (ecma_object_t *obj_p, ecma_string_t *property_name_p); +void ecma_builtin_object_list_lazy_property_keys (ecma_object_t *object_p, + ecma_collection_t *prop_names_p, + ecma_property_counter_t *prop_counter_p, + jerry_property_filter_t filter); + +void ecma_builtin_object_delete_lazy_property (ecma_object_t *object_p, ecma_string_t *property_name_p); + +/** + * Virtual function table for built-in object's internal methods + */ +#define ECMA_BUILT_IN_OBJ_VTABLE \ + [ECMA_OBJECT_TYPE_BUILT_IN_GENERAL] = { ecma_ordinary_object_get_prototype_of, \ + ecma_ordinary_object_set_prototype_of, \ + ecma_ordinary_object_is_extensible, \ + ecma_ordinary_object_prevent_extensions, \ + ecma_builtin_object_get_own_property, \ + ecma_ordinary_object_define_own_property, \ + ecma_ordinary_object_has_property, \ + ecma_ordinary_object_get, \ + ecma_ordinary_object_set, \ + ecma_ordinary_object_delete, \ + ecma_ordinary_object_own_property_keys, \ + ecma_ordinary_object_call, \ + ecma_ordinary_object_construct, \ + ecma_builtin_object_list_lazy_property_keys, \ + ecma_builtin_object_delete_lazy_property } + +/** + * Virtual function table for built-in class object's internal methods + */ +#define ECMA_BUILT_IN_CLASS_OBJ_VTABLE \ + [ECMA_OBJECT_TYPE_BUILT_IN_CLASS] = { ecma_ordinary_object_get_prototype_of, \ + ecma_ordinary_object_set_prototype_of, \ + ecma_ordinary_object_is_extensible, \ + ecma_ordinary_object_prevent_extensions, \ + ecma_builtin_object_get_own_property, \ + ecma_ordinary_object_define_own_property, \ + ecma_ordinary_object_has_property, \ + ecma_ordinary_object_get, \ + ecma_ordinary_object_set, \ + ecma_ordinary_object_delete, \ + ecma_ordinary_object_own_property_keys, \ + ecma_ordinary_object_call, \ + ecma_ordinary_object_construct, \ + ecma_builtin_object_list_lazy_property_keys, \ + ecma_builtin_object_delete_lazy_property } + #endif /* !ECMA_BUILTINS_H */ diff --git a/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype.c b/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype.c index 553cffda74..2cbc395394 100644 --- a/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype.c +++ b/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype.c @@ -156,7 +156,7 @@ ecma_builtin_typedarray_prototype_exec_routine (ecma_value_t this_arg, /**< this ecma_value_t call_args[] = { element, current_index, this_arg }; - ecma_value_t call_value = ecma_op_function_call (func_object_p, cb_this_arg, call_args, 3); + ecma_value_t call_value = ecma_internal_method_call (func_object_p, cb_this_arg, call_args, 3); ecma_fast_free_value (current_index); ecma_fast_free_value (element); @@ -273,7 +273,7 @@ ecma_builtin_typedarray_prototype_map (ecma_value_t this_arg, /**< this object * src_buffer_p += src_info_p->element_size; ecma_value_t call_args[] = { element, current_index, this_arg }; - ecma_value_t mapped_value = ecma_op_function_call (func_object_p, cb_this_arg, call_args, 3); + ecma_value_t mapped_value = ecma_internal_method_call (func_object_p, cb_this_arg, call_args, 3); ecma_free_value (current_index); ecma_free_value (element); @@ -384,7 +384,7 @@ ecma_builtin_typedarray_prototype_reduce_with_direction (ecma_value_t this_arg, JERRY_ASSERT (ecma_is_value_number (get_value) || ecma_is_value_bigint (get_value)); - ecma_value_t call_value = ecma_op_function_call (func_object_p, ECMA_VALUE_UNDEFINED, call_args, 4); + ecma_value_t call_value = ecma_internal_method_call (func_object_p, ECMA_VALUE_UNDEFINED, call_args, 4); ecma_fast_free_value (accumulator); ecma_fast_free_value (get_value); @@ -469,7 +469,7 @@ ecma_builtin_typedarray_prototype_filter (ecma_value_t this_arg, /**< this objec ecma_value_t call_args[] = { get_value, current_index, this_arg }; - ecma_value_t call_value = ecma_op_function_call (func_object_p, cb_this_arg, call_args, 3); + ecma_value_t call_value = ecma_internal_method_call (func_object_p, cb_this_arg, call_args, 3); ecma_fast_free_value (current_index); @@ -1185,7 +1185,7 @@ ecma_builtin_typedarray_prototype_sort_compare_helper (ecma_value_t lhs, /**< le ecma_value_t compare_args[] = { lhs, rhs }; - ecma_value_t call_value = ecma_op_function_call (comparefn_obj_p, ECMA_VALUE_UNDEFINED, compare_args, 2); + ecma_value_t call_value = ecma_internal_method_call (comparefn_obj_p, ECMA_VALUE_UNDEFINED, compare_args, 2); if (ECMA_IS_VALUE_ERROR (call_value) || ecma_is_value_number (call_value)) { @@ -1356,7 +1356,7 @@ ecma_builtin_typedarray_prototype_find_helper (ecma_value_t this_arg, /**< this buffer_p += info_p->element_size; ecma_value_t call_args[] = { element_value, ecma_make_uint32_value (buffer_index), this_arg }; - ecma_value_t call_value = ecma_op_function_call (func_object_p, predicate_this_arg, call_args, 3); + ecma_value_t call_value = ecma_internal_method_call (func_object_p, predicate_this_arg, call_args, 3); if (ECMA_IS_VALUE_ERROR (call_value)) { diff --git a/jerry-core/ecma/operations/ecma-arguments-object.c b/jerry-core/ecma/operations/ecma-arguments-object.c index 4d2894090c..d4a08642bb 100644 --- a/jerry-core/ecma/operations/ecma-arguments-object.c +++ b/jerry-core/ecma/operations/ecma-arguments-object.c @@ -22,9 +22,11 @@ #include "ecma-gc.h" #include "ecma-globals.h" #include "ecma-helpers.h" +#include "ecma-lcache.h" #include "ecma-lex-env.h" #include "ecma-objects-general.h" #include "ecma-objects.h" +#include "ecma-ordinary-object.h" #include "jrt.h" @@ -147,93 +149,113 @@ ecma_op_create_arguments_object (vm_frame_ctx_shared_args_t *shared_p, /**< shar } /* 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 + * Get the formal parameter name corresponding to the given property index * - * @return ecma value - * Returned value must be freed with ecma_free_value + * @return pointer to the formal parameter name */ -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 */ +static 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 */ { - /* 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.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED)) - { - return ret_value; - } + JERRY_ASSERT (mapped_arguments_p->unmapped.header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED); + JERRY_ASSERT (index < mapped_arguments_p->unmapped.header.u.cls.u2.formal_params_number); - ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) object_p; - uint32_t index = ecma_string_get_array_index (property_name_p); + ecma_compiled_code_t *byte_code_p; - if (index >= mapped_arguments_p->unmapped.header.u.cls.u2.formal_params_number) +#if JERRY_SNAPSHOT_EXEC + if (mapped_arguments_p->unmapped.header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_STATIC_BYTECODE) { - return ret_value; + byte_code_p = mapped_arguments_p->u.byte_code_p; } - - ecma_value_t *argv_p = (ecma_value_t *) (mapped_arguments_p + 1); - - if (ecma_is_value_empty (argv_p[index]) || argv_p[index] == ECMA_VALUE_ARGUMENT_NO_TRACK) + else +#endif /* JERRY_SNAPSHOT_EXEC */ { - return ret_value; + byte_code_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, mapped_arguments_p->u.byte_code); } - if (property_desc_p->flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED)) - { - ecma_free_value_if_not_object (argv_p[index]); - argv_p[index] = ECMA_VALUE_ARGUMENT_NO_TRACK; - return ret_value; - } + ecma_value_t *formal_param_names_p = ecma_compiled_code_resolve_arguments_start (byte_code_p); - if (property_desc_p->flags & JERRY_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); + return ecma_get_string_from_value (formal_param_names_p[index]); +} /* ecma_op_arguments_object_get_formal_parameter */ - ecma_value_t completion = ecma_op_set_mutable_binding (lex_env_p, name_p, property_desc_p->value, true); +/** + * ecma arguments object's [[GetOwnProperty]] internal method + * + * See also: + * ECMA-262 v12, 10.4.4.1 + * + * @return ecma property descriptor t + */ +ecma_property_descriptor_t +ecma_arguments_object_get_own_property (ecma_object_t *obj_p, /**< the object */ + ecma_string_t *property_name_p) /**< property name */ - JERRY_ASSERT (ecma_is_value_empty (completion)); - } +{ + ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); - if ((property_desc_p->flags & JERRY_PROP_IS_WRITABLE_DEFINED) && !(property_desc_p->flags & JERRY_PROP_IS_WRITABLE)) + prop_desc.u.property_p = ecma_find_named_property (obj_p, property_name_p); + + if (prop_desc.u.property_p != NULL) { - ecma_free_value_if_not_object (argv_p[index]); - argv_p[index] = ECMA_VALUE_ARGUMENT_NO_TRACK; - } + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; - return ret_value; -} /* ecma_op_arguments_object_define_own_property */ + if (ext_object_p->u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED) + { + uint32_t index = ecma_string_get_array_index (property_name_p); -/** - * 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_object_class_is (object_p, ECMA_OBJECT_CLASS_ARGUMENTS)); + if (index < ext_object_p->u.cls.u2.formal_params_number) + { + ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) ext_object_p; + + ecma_value_t *argv_p = (ecma_value_t *) (mapped_arguments_p + 1); + + if (!ecma_is_value_empty (argv_p[index]) && argv_p[index] != ECMA_VALUE_ARGUMENT_NO_TRACK) + { +#if JERRY_LCACHE + /* Mapped arguments initialized properties MUST not be lcached */ + if (ecma_is_property_lcached (prop_desc.u.property_p)) + { + jmem_cpointer_t prop_name_cp; + + 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 (obj_p, prop_name_cp, prop_desc.u.property_p); + } +#endif /* 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 (obj_p, + ECMA_PROPERTY_VALUE_PTR (prop_desc.u.property_p), + binding_value); + ecma_free_value (binding_value); + } + } + } - ecma_unmapped_arguments_t *arguments_p = (ecma_unmapped_arguments_t *) object_p; + prop_desc.flags = + ECMA_PROP_DESC_PROPERTY_FOUND | ECMA_PROPERTY_TO_PROPERTY_DESCRIPTOR_FLAGS (prop_desc.u.property_p); + return prop_desc; + } + + ecma_unmapped_arguments_t *arguments_p = (ecma_unmapped_arguments_t *) obj_p; ecma_value_t *argv_p = (ecma_value_t *) (arguments_p + 1); - ecma_property_value_t *prop_value_p; - ecma_property_t *prop_p; uint32_t arguments_number = arguments_p->header.u.cls.u3.arguments_number; uint8_t flags = arguments_p->header.u.cls.u1.arguments_flags; if (flags & ECMA_ARGUMENTS_OBJECT_MAPPED) { - argv_p = (ecma_value_t *) (((ecma_mapped_arguments_t *) object_p) + 1); + argv_p = (ecma_value_t *) (((ecma_mapped_arguments_t *) obj_p) + 1); } uint32_t index = ecma_string_get_array_index (property_name_p); @@ -242,33 +264,38 @@ ecma_op_arguments_object_try_to_lazy_instantiate_property (ecma_object_t *object { if (index >= arguments_number || ecma_is_value_empty (argv_p[index])) { - return NULL; + return prop_desc; } JERRY_ASSERT (argv_p[index] != ECMA_VALUE_ARGUMENT_NO_TRACK); - prop_value_p = ecma_create_named_data_property (object_p, - property_name_p, - ECMA_PROPERTY_BUILT_IN_CONFIGURABLE_ENUMERABLE_WRITABLE, - &prop_p); + prop_desc.flags = ECMA_PROP_DESC_PROPERTY_FOUND | ECMA_PROP_DESC_DATA_CONFIGURABLE_ENUMERABLE_WRITABLE; + ecma_property_value_t *prop_value_p = + ecma_create_named_data_property (obj_p, + property_name_p, + ECMA_PROPERTY_BUILT_IN_CONFIGURABLE_ENUMERABLE_WRITABLE, + &prop_desc.u.property_p); /* Passing the reference */ prop_value_p->value = argv_p[index]; argv_p[index] = ECMA_VALUE_UNDEFINED; - return prop_p; + return prop_desc; } if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_LENGTH) && !(flags & ECMA_ARGUMENTS_OBJECT_LENGTH_INITIALIZED)) { - prop_value_p = ecma_create_named_data_property (object_p, - ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH), - ECMA_PROPERTY_BUILT_IN_CONFIGURABLE_WRITABLE, - &prop_p); + prop_desc.flags = ECMA_PROP_DESC_PROPERTY_FOUND | ECMA_PROP_DESC_DATA_CONFIGURABLE_WRITABLE; + + ecma_property_value_t *prop_value_p = + ecma_create_named_data_property (obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH), + ECMA_PROPERTY_BUILT_IN_CONFIGURABLE_WRITABLE, + &prop_desc.u.property_p); prop_value_p->value = ecma_make_uint32_value (arguments_number); - return prop_p; + return prop_desc; } if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_CALLEE) @@ -276,10 +303,12 @@ ecma_op_arguments_object_try_to_lazy_instantiate_property (ecma_object_t *object { if (flags & ECMA_ARGUMENTS_OBJECT_MAPPED) { - prop_value_p = ecma_create_named_data_property (object_p, - property_name_p, - ECMA_PROPERTY_BUILT_IN_CONFIGURABLE_WRITABLE, - &prop_p); + prop_desc.flags = ECMA_PROP_DESC_PROPERTY_FOUND | ECMA_PROP_DESC_DATA_CONFIGURABLE_WRITABLE; + ecma_property_value_t *prop_value_p = + ecma_create_named_data_property (obj_p, + property_name_p, + ECMA_PROPERTY_BUILT_IN_CONFIGURABLE_WRITABLE, + &prop_desc.u.property_p); prop_value_p->value = arguments_p->callee; } @@ -287,14 +316,15 @@ ecma_op_arguments_object_try_to_lazy_instantiate_property (ecma_object_t *object { ecma_object_t *thrower_p = ecma_builtin_get (ECMA_BUILTIN_ID_TYPE_ERROR_THROWER); - ecma_create_named_accessor_property (object_p, + prop_desc.flags = ECMA_PROP_DESC_PROPERTY_FOUND; + ecma_create_named_accessor_property (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_CALLEE), thrower_p, thrower_p, ECMA_PROPERTY_BUILT_IN_FIXED, - &prop_p); + &prop_desc.u.property_p); } - return prop_p; + return prop_desc; } #if !JERRY_ESNEXT @@ -302,102 +332,205 @@ ecma_op_arguments_object_try_to_lazy_instantiate_property (ecma_object_t *object { if (arguments_p->header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED) { - return NULL; + return prop_desc; } ecma_object_t *thrower_p = ecma_builtin_get (ECMA_BUILTIN_ID_TYPE_ERROR_THROWER); - ecma_create_named_accessor_property (object_p, + prop_desc.flags = ECMA_PROP_DESC_PROPERTY_FOUND; + ecma_create_named_accessor_property (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_CALLER), thrower_p, thrower_p, ECMA_PROPERTY_BUILT_IN_FIXED, - &prop_p); - return prop_p; + &prop_desc.u.property_p); + return prop_desc; } #else /* JERRY_ESNEXT */ if (ecma_op_compare_string_to_global_symbol (property_name_p, LIT_GLOBAL_SYMBOL_ITERATOR) && !(flags & ECMA_ARGUMENTS_OBJECT_ITERATOR_INITIALIZED)) { - prop_value_p = ecma_create_named_data_property (object_p, - property_name_p, - ECMA_PROPERTY_BUILT_IN_CONFIGURABLE_WRITABLE, - &prop_p); + prop_desc.flags = ECMA_PROP_DESC_PROPERTY_FOUND | ECMA_PROP_DESC_DATA_CONFIGURABLE_WRITABLE; + ecma_property_value_t *prop_value_p = ecma_create_named_data_property (obj_p, + property_name_p, + ECMA_PROPERTY_BUILT_IN_CONFIGURABLE_WRITABLE, + &prop_desc.u.property_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)); - return prop_p; + return prop_desc; } #endif /* !JERRY_ESNEXT */ - return NULL; -} /* ecma_op_arguments_object_try_to_lazy_instantiate_property */ + return prop_desc; +} /* ecma_arguments_object_get_own_property */ /** - * Delete configurable properties of arguments object + * ecma arguments object's [[Get]] internal method + * + * See also: + * ECMA-262 v12, 10.4.4.3 + * + * @return ecma value t */ -void -ecma_op_arguments_delete_built_in_property (ecma_object_t *object_p, /**< the object */ - ecma_string_t *property_name_p) /**< property name */ +ecma_value_t +ecma_arguments_object_get (ecma_object_t *obj_p, /**< the object */ + ecma_string_t *property_name_p, /**< property name */ + ecma_value_t receiver) /**< receiver */ + { - ecma_unmapped_arguments_t *arguments_p = (ecma_unmapped_arguments_t *) object_p; + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; - if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_LENGTH)) + if (!(ext_object_p->u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED)) { - JERRY_ASSERT (!(arguments_p->header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_LENGTH_INITIALIZED)); - - arguments_p->header.u.cls.u1.arguments_flags |= ECMA_ARGUMENTS_OBJECT_LENGTH_INITIALIZED; - return; + return ecma_ordinary_object_get (obj_p, property_name_p, receiver); } - if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_CALLEE)) + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index < ext_object_p->u.cls.u2.formal_params_number) { - JERRY_ASSERT (!(arguments_p->header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_CALLEE_INITIALIZED)); - JERRY_ASSERT (arguments_p->header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED); + ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) ext_object_p; - arguments_p->header.u.cls.u1.arguments_flags |= ECMA_ARGUMENTS_OBJECT_CALLEE_INITIALIZED; - return; + ecma_value_t *argv_p = (ecma_value_t *) (mapped_arguments_p + 1); + + /* 2. */ + if (!ecma_is_value_empty (argv_p[index]) && argv_p[index] != ECMA_VALUE_ARGUMENT_NO_TRACK) + { + /* 3. */ + 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, name_p, true); + } } -#if JERRY_ESNEXT - if (ecma_prop_name_is_symbol (property_name_p)) + /* 4. */ + return ecma_ordinary_object_get (obj_p, property_name_p, receiver); +} /* ecma_arguments_object_get */ + +/** + * ecma arguments object's [[Set]] internal method + * + * See also: + * ECMA-262 v12, 10.4.4.4 + * + * @return ecma value t + */ +ecma_value_t +ecma_arguments_object_set (ecma_object_t *obj_p, /**< the object */ + ecma_string_t *property_name_p, /**< property name */ + ecma_value_t value, /**< ecma value */ + ecma_value_t receiver, /**< receiver */ + bool is_throw) /**< flag that controls failure handling */ +{ + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; + + /* 1. */ + if (!(ext_object_p->u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED)) { - JERRY_ASSERT (!(arguments_p->header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_ITERATOR_INITIALIZED)); - JERRY_ASSERT (ecma_op_compare_string_to_global_symbol (property_name_p, LIT_GLOBAL_SYMBOL_ITERATOR)); + return ecma_ordinary_object_set (obj_p, property_name_p, value, receiver, is_throw); + } - arguments_p->header.u.cls.u1.arguments_flags |= ECMA_ARGUMENTS_OBJECT_ITERATOR_INITIALIZED; - return; + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index < ext_object_p->u.cls.u2.formal_params_number) + { + ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) ext_object_p; + + ecma_value_t *argv_p = (ecma_value_t *) (mapped_arguments_p + 1); + + /* 2.b */ + if (!ecma_is_value_empty (argv_p[index]) && argv_p[index] != ECMA_VALUE_ARGUMENT_NO_TRACK) + { + /* 3.a */ + 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; + } } -#endif /* JERRY_ESNEXT */ + /* 4. */ + return ecma_ordinary_object_set (obj_p, property_name_p, value, receiver, is_throw); +} /* ecma_arguments_object_set */ + +/** + * ecma arguments object's [[DefineOwnProperty]] internal method + * + * See also: + * ECMA-262 v12, 10.4.4.2 + * + * @return ecma value t + */ +ecma_value_t +ecma_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_ordinary_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.cls.u1.arguments_flags & 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); - ecma_value_t *argv_p = (ecma_value_t *) (arguments_p + 1); + if (index >= mapped_arguments_p->unmapped.header.u.cls.u2.formal_params_number) + { + return ret_value; + } - if (arguments_p->header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED) + ecma_value_t *argv_p = (ecma_value_t *) (mapped_arguments_p + 1); + + if (ecma_is_value_empty (argv_p[index]) || argv_p[index] == ECMA_VALUE_ARGUMENT_NO_TRACK) { - argv_p = (ecma_value_t *) (((ecma_mapped_arguments_t *) object_p) + 1); + return ret_value; } - JERRY_ASSERT (argv_p[index] == ECMA_VALUE_UNDEFINED || argv_p[index] == ECMA_VALUE_ARGUMENT_NO_TRACK); + if (property_desc_p->flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED)) + { + ecma_free_value_if_not_object (argv_p[index]); + argv_p[index] = ECMA_VALUE_ARGUMENT_NO_TRACK; + return ret_value; + } - argv_p[index] = ECMA_VALUE_EMPTY; -} /* ecma_op_arguments_delete_built_in_property */ + if (property_desc_p->flags & JERRY_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 & JERRY_PROP_IS_WRITABLE_DEFINED) && !(property_desc_p->flags & JERRY_PROP_IS_WRITABLE)) + { + ecma_free_value_if_not_object (argv_p[index]); + argv_p[index] = ECMA_VALUE_ARGUMENT_NO_TRACK; + } + + return ret_value; +} /* ecma_arguments_object_define_own_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, /**< property counters */ - jerry_property_filter_t filter) /**< property name filter options */ +ecma_arguments_object_list_lazy_property_keys (ecma_object_t *obj_p, /**< arguments object */ + ecma_collection_t *prop_names_p, /**< prop name collection */ + ecma_property_counter_t *prop_counter_p, /**< property counters */ + jerry_property_filter_t filter) /**< property name filter options */ { - JERRY_ASSERT (ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_ARGUMENTS)); - ecma_unmapped_arguments_t *arguments_p = (ecma_unmapped_arguments_t *) obj_p; uint32_t arguments_number = arguments_p->header.u.cls.u3.arguments_number; @@ -454,38 +587,58 @@ ecma_op_arguments_object_list_lazy_property_names (ecma_object_t *obj_p, /**< ar prop_counter_p->symbol_named_props++; } #endif /* JERRY_ESNEXT */ -} /* ecma_op_arguments_object_list_lazy_property_names */ +} /* ecma_arguments_object_list_lazy_property_keys */ /** - * Get the formal parameter name corresponding to the given property index - * - * @return pointer to the formal parameter name + * Delete configurable properties of arguments object */ -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 */ +void +ecma_arguments_object_delete_lazy_property (ecma_object_t *object_p, /**< the object */ + ecma_string_t *property_name_p) /**< property name */ { - JERRY_ASSERT (mapped_arguments_p->unmapped.header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED); - JERRY_ASSERT (index < mapped_arguments_p->unmapped.header.u.cls.u2.formal_params_number); + ecma_unmapped_arguments_t *arguments_p = (ecma_unmapped_arguments_t *) object_p; - ecma_compiled_code_t *byte_code_p; + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_LENGTH)) + { + JERRY_ASSERT (!(arguments_p->header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_LENGTH_INITIALIZED)); -#if JERRY_SNAPSHOT_EXEC - if (mapped_arguments_p->unmapped.header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_STATIC_BYTECODE) + arguments_p->header.u.cls.u1.arguments_flags |= ECMA_ARGUMENTS_OBJECT_LENGTH_INITIALIZED; + return; + } + + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_CALLEE)) { - byte_code_p = mapped_arguments_p->u.byte_code_p; + JERRY_ASSERT (!(arguments_p->header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_CALLEE_INITIALIZED)); + JERRY_ASSERT (arguments_p->header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED); + + arguments_p->header.u.cls.u1.arguments_flags |= ECMA_ARGUMENTS_OBJECT_CALLEE_INITIALIZED; + return; } - else -#endif /* JERRY_SNAPSHOT_EXEC */ + +#if JERRY_ESNEXT + if (ecma_prop_name_is_symbol (property_name_p)) { - byte_code_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t, mapped_arguments_p->u.byte_code); + JERRY_ASSERT (!(arguments_p->header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_ITERATOR_INITIALIZED)); + JERRY_ASSERT (ecma_op_compare_string_to_global_symbol (property_name_p, LIT_GLOBAL_SYMBOL_ITERATOR)); + + arguments_p->header.u.cls.u1.arguments_flags |= ECMA_ARGUMENTS_OBJECT_ITERATOR_INITIALIZED; + return; } +#endif /* JERRY_ESNEXT */ - ecma_value_t *formal_param_names_p = ecma_compiled_code_resolve_arguments_start (byte_code_p); + uint32_t index = ecma_string_get_array_index (property_name_p); - return ecma_get_string_from_value (formal_param_names_p[index]); -} /* ecma_op_arguments_object_get_formal_parameter */ + ecma_value_t *argv_p = (ecma_value_t *) (arguments_p + 1); + + if (arguments_p->header.u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED) + { + argv_p = (ecma_value_t *) (((ecma_mapped_arguments_t *) object_p) + 1); + } + + JERRY_ASSERT (argv_p[index] == ECMA_VALUE_UNDEFINED || argv_p[index] == ECMA_VALUE_ARGUMENT_NO_TRACK); + + argv_p[index] = ECMA_VALUE_EMPTY; +} /* ecma_arguments_object_delete_lazy_property */ /** * @} diff --git a/jerry-core/ecma/operations/ecma-arguments-object.h b/jerry-core/ecma/operations/ecma-arguments-object.h index 755b755c4c..6525c85d14 100644 --- a/jerry-core/ecma/operations/ecma-arguments-object.h +++ b/jerry-core/ecma/operations/ecma-arguments-object.h @@ -23,20 +23,41 @@ ecma_value_t ecma_op_create_arguments_object (vm_frame_ctx_shared_args_t *shared_p, ecma_object_t *lex_env_p); -ecma_value_t ecma_op_arguments_object_define_own_property (ecma_object_t *object_p, - ecma_string_t *property_name_p, - const ecma_property_descriptor_t *property_desc_p); - -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_delete_built_in_property (ecma_object_t *object_p, ecma_string_t *property_name_p); - -void ecma_op_arguments_object_list_lazy_property_names (ecma_object_t *obj_p, - ecma_collection_t *prop_names_p, - ecma_property_counter_t *prop_counter_p, - jerry_property_filter_t filter); +ecma_property_descriptor_t ecma_arguments_object_get_own_property (ecma_object_t *obj_p, + ecma_string_t *property_name_p); +ecma_value_t ecma_arguments_object_get (ecma_object_t *obj_p, ecma_string_t *property_name_p, ecma_value_t receiver); +ecma_value_t ecma_arguments_object_set (ecma_object_t *obj_p, + ecma_string_t *property_name_p, + ecma_value_t value, + ecma_value_t receiver, + bool is_throw); +ecma_value_t ecma_arguments_object_define_own_property (ecma_object_t *object_p, + ecma_string_t *property_name_p, + const ecma_property_descriptor_t *property_desc_p); +void ecma_arguments_object_list_lazy_property_keys (ecma_object_t *obj_p, + ecma_collection_t *prop_names_p, + ecma_property_counter_t *prop_counter_p, + jerry_property_filter_t filter); +void ecma_arguments_object_delete_lazy_property (ecma_object_t *object_p, ecma_string_t *property_name_p); + +/** + * Virtual function table for arguments object's internal methods + */ +#define ECMA_ARGUMENTS_OBJ_VTABLE \ + [ECMA_OBJECT_CLASS_ARGUMENTS] = { NULL, \ + NULL, \ + NULL, \ + NULL, \ + ecma_arguments_object_get_own_property, \ + ecma_arguments_object_define_own_property, \ + NULL, \ + ecma_arguments_object_get, \ + ecma_arguments_object_set, \ + ecma_ordinary_object_delete, \ + NULL, \ + NULL, \ + NULL, \ + ecma_arguments_object_list_lazy_property_keys, \ + ecma_arguments_object_delete_lazy_property } -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-array-object.c b/jerry-core/ecma/operations/ecma-array-object.c index b150a9800a..c83bda8fff 100644 --- a/jerry-core/ecma/operations/ecma-array-object.c +++ b/jerry-core/ecma/operations/ecma-array-object.c @@ -26,6 +26,7 @@ #include "ecma-iterator-object.h" #include "ecma-objects-general.h" #include "ecma-objects.h" +#include "ecma-ordinary-object.h" #include "ecma-property-hashmap.h" /** \addtogroup ecma ECMA @@ -40,6 +41,16 @@ */ #define ECMA_FAST_ARRAY_UINT_DIRECT_STRING_PROP_TYPE (ECMA_DIRECT_STRING_UINT << ECMA_PROPERTY_NAME_TYPE_SHIFT) +/** + * Property descriptor bitset for fast array data properties. + * If the property desciptor fields contains all the flags below + * attempt to stay fast access array during [[DefineOwnProperty]] operation. + */ +#define ECMA_FAST_ARRAY_DATA_PROP_FLAGS \ + (JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_ENUMERABLE_DEFINED | JERRY_PROP_IS_ENUMERABLE \ + | JERRY_PROP_IS_CONFIGURABLE_DEFINED | JERRY_PROP_IS_CONFIGURABLE | JERRY_PROP_IS_WRITABLE_DEFINED \ + | JERRY_PROP_IS_WRITABLE) + /** * Allocate a new array object with the given length * @@ -477,45 +488,401 @@ ecma_fast_array_extend (ecma_object_t *object_p, /**< fast access mode array obj } /* ecma_fast_array_extend */ /** - * Delete the array object's property referenced by its value pointer. + * ecma array object's [[DefineOwnProperty]] internal method * - * Note: specified property must be owned by specified object. + * See also: + * ECMA-262 v12, 10.4.2.1 * - * @return true, if the property is deleted - * false, otherwise + * @return ecma value t */ -bool -ecma_array_object_delete_property (ecma_object_t *object_p, /**< object */ - ecma_string_t *property_name_p) /**< property name */ +ecma_value_t +ecma_array_object_define_own_property (ecma_object_t *object_p, /**< the array object */ + ecma_string_t *property_name_p, /**< property name */ + const ecma_property_descriptor_t *property_desc_p) /**< property descriptor */ { - JERRY_ASSERT (ecma_get_object_base_type (object_p) == ECMA_OBJECT_BASE_TYPE_ARRAY); - ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; + if (ecma_string_is_length (property_name_p)) + { + JERRY_ASSERT ((property_desc_p->flags & JERRY_PROP_IS_CONFIGURABLE_DEFINED) + || !(property_desc_p->flags & JERRY_PROP_IS_CONFIGURABLE)); + JERRY_ASSERT ((property_desc_p->flags & JERRY_PROP_IS_ENUMERABLE_DEFINED) + || !(property_desc_p->flags & JERRY_PROP_IS_ENUMERABLE)); + JERRY_ASSERT ((property_desc_p->flags & JERRY_PROP_IS_WRITABLE_DEFINED) + || !(property_desc_p->flags & JERRY_PROP_IS_WRITABLE)); - if (!ecma_op_object_is_fast_array (object_p)) + if (property_desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED) + { + return ecma_op_array_object_set_length (object_p, property_desc_p->value, property_desc_p->flags); + } + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + ecma_value_t length_value = ecma_make_uint32_value (ext_object_p->u.array.length); + + ecma_value_t result = ecma_op_array_object_set_length (object_p, length_value, property_desc_p->flags); + + ecma_fast_free_value (length_value); + return result; + } + + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + + if (ecma_op_object_is_fast_array (object_p)) { - return false; + if ((property_desc_p->flags & ECMA_FAST_ARRAY_DATA_PROP_FLAGS) == ECMA_FAST_ARRAY_DATA_PROP_FLAGS) + { + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (JERRY_UNLIKELY (index == ECMA_STRING_NOT_ARRAY_INDEX)) + { + ecma_fast_array_convert_to_normal (object_p); + } + else if (ecma_fast_array_set_property (object_p, index, property_desc_p->value)) + { + return ECMA_VALUE_TRUE; + } + + JERRY_ASSERT (!ecma_op_array_is_fast_array (ext_object_p)); + } + else + { + ecma_fast_array_convert_to_normal (object_p); + } + } + + JERRY_ASSERT (!ecma_op_object_is_fast_array (object_p)); + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index == ECMA_STRING_NOT_ARRAY_INDEX) + { + return ecma_ordinary_object_define_own_property (object_p, property_name_p, property_desc_p); + } + + bool update_length = (index >= ext_object_p->u.array.length); + + if (update_length && !ecma_is_property_writable ((ecma_property_t) ext_object_p->u.array.length_prop_and_hole_count)) + { + return ecma_raise_property_redefinition (property_name_p, property_desc_p->flags); + } + + ecma_property_descriptor_t prop_desc; + + prop_desc = *property_desc_p; + prop_desc.flags &= (uint16_t) ~JERRY_PROP_SHOULD_THROW; + + ecma_value_t completition = ecma_ordinary_object_define_own_property (object_p, property_name_p, &prop_desc); + JERRY_ASSERT (ecma_is_value_boolean (completition)); + + if (ecma_is_value_false (completition)) + { + return ecma_raise_property_redefinition (property_name_p, property_desc_p->flags); + } + + if (update_length) + { + ext_object_p->u.array.length = index + 1; } - JERRY_ASSERT (object_p->u1.property_list_cp != JMEM_CP_NULL); + return ECMA_VALUE_TRUE; +} /* ecma_array_object_define_own_property */ + +/** + * ecma array object's [[GetOwnProperty]] internal method + * + * @return ecma value t + */ +ecma_property_descriptor_t +ecma_array_object_get_own_property (ecma_object_t *obj_p, /**< the object */ + ecma_string_t *property_name_p) /**< property name */ +{ + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; + + ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); + + if (ecma_string_is_length (property_name_p)) + { + prop_desc.flags = ECMA_PROP_DESC_VIRTUAL_FOUND | JERRY_PROP_IS_WRITABLE_DEFINED + | (ext_object_p->u.array.length_prop_and_hole_count & ECMA_PROPERTY_FLAG_WRITABLE); + prop_desc.value = ecma_make_uint32_value (ext_object_p->u.array.length); + + return prop_desc; + } + + if (ecma_op_array_is_fast_array (ext_object_p)) + { + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index != ECMA_STRING_NOT_ARRAY_INDEX) + { + if (JERRY_LIKELY (index < ext_object_p->u.array.length)) + { + ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, obj_p->u1.property_list_cp); + + if (ecma_is_value_array_hole (values_p[index])) + { + return prop_desc; + } + + prop_desc.flags = ECMA_PROP_DESC_VIRTUAL_FOUND | ECMA_PROP_DESC_DATA_CONFIGURABLE_ENUMERABLE_WRITABLE; + prop_desc.value = ecma_fast_copy_value (values_p[index]); + return prop_desc; + } + } + + return prop_desc; + } + + ecma_free_property_descriptor (&prop_desc); + + return ecma_ordinary_object_get_own_property (obj_p, property_name_p); +} /* ecma_array_object_get_own_property */ + +/** + * ecma built-in array object's [[GetOwnProperty]] internal method + * + * @return ecma property descriptor t + */ +ecma_property_descriptor_t +ecma_builtin_array_object_get_own_property (ecma_object_t *obj_p, /**< the object */ + ecma_string_t *property_name_p) /**< property name */ +{ + ecma_property_descriptor_t prop_desc = ecma_array_object_get_own_property (obj_p, property_name_p); + + if (ecma_property_descriptor_found (&prop_desc)) + { + return prop_desc; + } + + return ecma_builtin_object_get_own_property (obj_p, property_name_p); +} /* ecma_builtin_array_object_get_own_property */ + +/** + * ecma array object's [[Get]] internal method + * + * @return ecma value t + */ +ecma_value_t +ecma_array_object_get (ecma_object_t *obj_p, /**< the object */ + ecma_string_t *property_name_p, /**< property name */ + ecma_value_t receiver) /**< receiver */ + +{ + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; + + /* Fast path */ + if (ecma_string_is_length (property_name_p)) + { + return ecma_make_uint32_value (ext_object_p->u.array.length); + } + + /* Fast path */ + if (JERRY_LIKELY (ecma_op_array_is_fast_array (ext_object_p))) + { + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (JERRY_LIKELY (index != ECMA_STRING_NOT_ARRAY_INDEX)) + { + if (JERRY_LIKELY (index < ext_object_p->u.array.length)) + { + ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, obj_p->u1.property_list_cp); + + if (!ecma_is_value_array_hole (values_p[index])) + { + return ecma_fast_copy_value (values_p[index]); + } + } + } + + jmem_cpointer_t proto_cp = ecma_object_get_prototype_of (obj_p); + + JERRY_ASSERT (proto_cp != JMEM_CP_NULL); + + ecma_object_t *proto_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, proto_cp); + + return ecma_internal_method_get (proto_p, property_name_p, receiver); + } + + return ecma_ordinary_object_get (obj_p, property_name_p, receiver); +} /* ecma_array_object_get */ + +/** + * ecma array object's [[Set]] internal method + * + * @return ecma value t + */ +ecma_value_t +ecma_array_object_set (ecma_object_t *obj_p, /**< the object */ + ecma_string_t *property_name_p, /**< property name */ + ecma_value_t value, /**< ecma value */ + ecma_value_t receiver, /**< receiver */ + bool is_throw) /**< flag that controls failure handling */ +{ + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; + + /* Fast path */ + if (JERRY_LIKELY (receiver == ecma_make_object_value (obj_p))) + { + if (ecma_string_is_length (property_name_p)) + { + if (ecma_is_property_writable ((ecma_property_t) ext_object_p->u.array.length_prop_and_hole_count)) + { + return ecma_op_array_object_set_length (obj_p, value, 0); + } + + return ecma_raise_readonly_assignment (property_name_p, is_throw); + } + + if (JERRY_LIKELY (ecma_op_array_is_fast_array (ext_object_p))) + { + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (JERRY_UNLIKELY (index == ECMA_STRING_NOT_ARRAY_INDEX)) + { + ecma_fast_array_convert_to_normal (obj_p); + } + else if (ecma_fast_array_set_property (obj_p, index, value)) + { + return ECMA_VALUE_TRUE; + } + } + } + + return ecma_ordinary_object_set (obj_p, property_name_p, value, receiver, is_throw); +} /* ecma_array_object_set */ + +/** + * ecma array object's [[Delet]] internal method + * + * @return ecma value t + */ +ecma_value_t +ecma_array_object_delete (ecma_object_t *obj_p, /**< the object */ + ecma_string_t *property_name_p, /**< property name */ + bool is_throw) /**< flag that controls failure handling */ +{ + if (!ecma_op_object_is_fast_array (obj_p)) + { + return ecma_ordinary_object_delete (obj_p, property_name_p, is_throw); + } + + ecma_property_descriptor_t prop_desc = ecma_array_object_get_own_property (obj_p, property_name_p); + + if (!ecma_property_descriptor_found (&prop_desc)) + { + return ECMA_VALUE_TRUE; + } + + if (!ecma_property_descriptor_is_configurable (&prop_desc)) + { + ecma_free_virtual_property_descriptor (&prop_desc); + return ecma_raise_non_configurable_property (property_name_p, is_throw); + } + + ecma_free_virtual_property_descriptor (&prop_desc); + + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; uint32_t index = ecma_string_get_array_index (property_name_p); JERRY_ASSERT (index != ECMA_STRING_NOT_ARRAY_INDEX); - JERRY_ASSERT (index < ext_obj_p->u.array.length); - ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp); + if (obj_p->u1.property_list_cp == JMEM_CP_NULL || index >= ext_obj_p->u.array.length) + { + return ECMA_VALUE_TRUE; + } - if (ecma_is_value_array_hole (values_p[index])) + ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, obj_p->u1.property_list_cp); + + if (!ecma_is_value_array_hole (values_p[index])) { - return true; + ecma_free_value_if_not_object (values_p[index]); + + values_p[index] = ECMA_VALUE_ARRAY_HOLE; + ext_obj_p->u.array.length_prop_and_hole_count += ECMA_FAST_ARRAY_HOLE_ONE; } - ecma_free_value_if_not_object (values_p[index]); + return ECMA_VALUE_TRUE; +} /* ecma_array_object_delete */ - values_p[index] = ECMA_VALUE_ARRAY_HOLE; - ext_obj_p->u.array.length_prop_and_hole_count += ECMA_FAST_ARRAY_HOLE_ONE; - return true; -} /* ecma_array_object_delete_property */ +/** + * Get collection of property names of a fast access mode array object + * + * Note: Since the fast array object only contains indexed, enumerable, writable, configurable properties + * we can return a collection of non-array hole array indices + * + * @return collection of strings - property names + */ +static ecma_collection_t * +ecma_fast_array_object_own_property_keys (ecma_object_t *object_p, /**< fast access mode array object */ + jerry_property_filter_t filter) /**< property name filter options */ +{ + JERRY_ASSERT (ecma_op_object_is_fast_array (object_p)); + + ecma_collection_t *ret_p = ecma_new_collection (); + + if (!(filter & JERRY_PROPERTY_FILTER_EXCLUDE_INTEGER_INDICES)) + { + ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; + uint32_t length = ext_obj_p->u.array.length; + + if (length != 0) + { + ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp); + + for (uint32_t i = 0; i < length; i++) + { + if (ecma_is_value_array_hole (values_p[i])) + { + continue; + } + + ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (i); + + ecma_collection_push_back (ret_p, ecma_make_string_value (index_str_p)); + } + } + } + + if (!(filter & JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS)) + { + ecma_collection_push_back (ret_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); + } + + return ret_p; +} /* ecma_fast_array_object_own_property_keys */ + +/** + * ecma array object's [[OwnPropertyKeys]] internal method + * + * @return ecma collection t pointer + */ +ecma_collection_t * +ecma_array_object_own_property_keys (ecma_object_t *obj_p, /**< object */ + jerry_property_filter_t filter) /**< name filters */ +{ + if (ecma_op_object_is_fast_array (obj_p)) + { + return ecma_fast_array_object_own_property_keys (obj_p, filter); + } + + return ecma_ordinary_object_own_property_keys (obj_p, filter); +} /* ecma_array_object_own_property_keys */ + +/** + * List lazy instantiated property names of array object + */ +void +ecma_array_object_list_lazy_property_keys (ecma_object_t *obj_p, /**< object */ + ecma_collection_t *prop_names_p, /**< property names */ + ecma_property_counter_t *prop_counter_p, /**< property counter */ + jerry_property_filter_t filter) /**< name filters */ +{ + JERRY_UNUSED (obj_p); + + if (!(filter & JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS)) + { + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); + prop_counter_p->string_named_props++; + } +} /* ecma_array_object_list_lazy_property_keys */ /** * Low level delete of fast access mode array items @@ -616,53 +983,6 @@ ecma_fast_array_set_length (ecma_object_t *object_p, /**< fast access mode array } } /* ecma_fast_array_set_length */ -/** - * Get collection of property names of a fast access mode array object - * - * Note: Since the fast array object only contains indexed, enumerable, writable, configurable properties - * we can return a collection of non-array hole array indices - * - * @return collection of strings - property names - */ -ecma_collection_t * -ecma_fast_array_object_own_property_keys (ecma_object_t *object_p, /**< fast access mode array object */ - jerry_property_filter_t filter) /**< property name filter options */ -{ - JERRY_ASSERT (ecma_op_object_is_fast_array (object_p)); - - ecma_collection_t *ret_p = ecma_new_collection (); - - if (!(filter & JERRY_PROPERTY_FILTER_EXCLUDE_INTEGER_INDICES)) - { - ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) object_p; - uint32_t length = ext_obj_p->u.array.length; - - if (length != 0) - { - ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp); - - for (uint32_t i = 0; i < length; i++) - { - if (ecma_is_value_array_hole (values_p[i])) - { - continue; - } - - ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (i); - - ecma_collection_push_back (ret_p, ecma_make_string_value (index_str_p)); - } - } - } - - if (!(filter & JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS)) - { - ecma_collection_push_back (ret_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); - } - - return ret_p; -} /* ecma_fast_array_object_own_property_keys */ - #if JERRY_ESNEXT /** * Array object creation with custom prototype. @@ -742,7 +1062,7 @@ ecma_op_array_species_create (ecma_object_t *original_array_p, /**< The object f ecma_value_t len_val = ecma_make_length_value (length); ecma_object_t *ctor_object_p = ecma_get_object_from_value (constructor); - ecma_value_t ret_val = ecma_op_function_construct (ctor_object_p, ctor_object_p, &len_val, 1); + ecma_value_t ret_val = ecma_internal_method_construct (ctor_object_p, ctor_object_p, &len_val, 1); ecma_deref_object (ctor_object_p); ecma_free_value (len_val); @@ -950,7 +1270,7 @@ ecma_delete_array_properties (ecma_object_t *object_p, /**< object */ ecma_value_t ecma_op_array_object_set_length (ecma_object_t *object_p, /**< the array object */ ecma_value_t new_value, /**< new length value */ - uint16_t flags) /**< property descriptor flags */ + uint32_t flags) /**< property descriptor flags */ { ecma_number_t new_len_num; ecma_value_t completion = ecma_op_to_number (new_value, &new_len_num); @@ -1047,115 +1367,6 @@ ecma_op_array_object_set_length (ecma_object_t *object_p, /**< the array object return ecma_raise_property_redefinition (ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH), flags); } /* ecma_op_array_object_set_length */ -/** - * Property descriptor bitset for fast array data properties. - * If the property desciptor fields contains all the flags below - * attempt to stay fast access array during [[DefineOwnProperty]] operation. - */ -#define ECMA_FAST_ARRAY_DATA_PROP_FLAGS \ - (JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_ENUMERABLE_DEFINED | JERRY_PROP_IS_ENUMERABLE \ - | JERRY_PROP_IS_CONFIGURABLE_DEFINED | JERRY_PROP_IS_CONFIGURABLE | JERRY_PROP_IS_WRITABLE_DEFINED \ - | JERRY_PROP_IS_WRITABLE) - -/** - * [[DefineOwnProperty]] ecma array object's operation - * - * See also: - * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 - * ECMA-262 v5, 15.4.5.1 - * - * @return ecma value - * Returned value must be freed with ecma_free_value - */ -ecma_value_t -ecma_op_array_object_define_own_property (ecma_object_t *object_p, /**< the array object */ - ecma_string_t *property_name_p, /**< property name */ - const ecma_property_descriptor_t *property_desc_p) /**< property descriptor */ -{ - if (ecma_string_is_length (property_name_p)) - { - JERRY_ASSERT ((property_desc_p->flags & JERRY_PROP_IS_CONFIGURABLE_DEFINED) - || !(property_desc_p->flags & JERRY_PROP_IS_CONFIGURABLE)); - JERRY_ASSERT ((property_desc_p->flags & JERRY_PROP_IS_ENUMERABLE_DEFINED) - || !(property_desc_p->flags & JERRY_PROP_IS_ENUMERABLE)); - JERRY_ASSERT ((property_desc_p->flags & JERRY_PROP_IS_WRITABLE_DEFINED) - || !(property_desc_p->flags & JERRY_PROP_IS_WRITABLE)); - - if (property_desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED) - { - return ecma_op_array_object_set_length (object_p, property_desc_p->value, property_desc_p->flags); - } - - ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; - ecma_value_t length_value = ecma_make_uint32_value (ext_object_p->u.array.length); - - ecma_value_t result = ecma_op_array_object_set_length (object_p, length_value, property_desc_p->flags); - - ecma_fast_free_value (length_value); - return result; - } - - ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; - - if (ecma_op_object_is_fast_array (object_p)) - { - if ((property_desc_p->flags & ECMA_FAST_ARRAY_DATA_PROP_FLAGS) == ECMA_FAST_ARRAY_DATA_PROP_FLAGS) - { - uint32_t index = ecma_string_get_array_index (property_name_p); - - if (JERRY_UNLIKELY (index == ECMA_STRING_NOT_ARRAY_INDEX)) - { - ecma_fast_array_convert_to_normal (object_p); - } - else if (ecma_fast_array_set_property (object_p, index, property_desc_p->value)) - { - return ECMA_VALUE_TRUE; - } - - JERRY_ASSERT (!ecma_op_array_is_fast_array (ext_object_p)); - } - else - { - ecma_fast_array_convert_to_normal (object_p); - } - } - - JERRY_ASSERT (!ecma_op_object_is_fast_array (object_p)); - uint32_t index = ecma_string_get_array_index (property_name_p); - - if (index == ECMA_STRING_NOT_ARRAY_INDEX) - { - return ecma_op_general_object_define_own_property (object_p, property_name_p, property_desc_p); - } - - bool update_length = (index >= ext_object_p->u.array.length); - - if (update_length && !ecma_is_property_writable ((ecma_property_t) ext_object_p->u.array.length_prop_and_hole_count)) - { - return ecma_raise_property_redefinition (property_name_p, property_desc_p->flags); - } - - ecma_property_descriptor_t prop_desc; - - prop_desc = *property_desc_p; - prop_desc.flags &= (uint16_t) ~JERRY_PROP_SHOULD_THROW; - - ecma_value_t completition = ecma_op_general_object_define_own_property (object_p, property_name_p, &prop_desc); - JERRY_ASSERT (ecma_is_value_boolean (completition)); - - if (ecma_is_value_false (completition)) - { - return ecma_raise_property_redefinition (property_name_p, property_desc_p->flags); - } - - if (update_length) - { - ext_object_p->u.array.length = index + 1; - } - - return ECMA_VALUE_TRUE; -} /* ecma_op_array_object_define_own_property */ - /** * Get the length of the an array object * @@ -1205,7 +1416,7 @@ ecma_array_object_to_string (ecma_value_t this_arg) /**< this argument */ /* 4. */ ecma_object_t *join_func_obj_p = ecma_get_object_from_value (join_value); - ret_value = ecma_op_function_call (join_func_obj_p, this_arg, NULL, 0); + ret_value = ecma_internal_method_call (join_func_obj_p, this_arg, NULL, 0); } ecma_free_value (join_value); diff --git a/jerry-core/ecma/operations/ecma-array-object.h b/jerry-core/ecma/operations/ecma-array-object.h index d2d55f905e..1ee245e007 100644 --- a/jerry-core/ecma/operations/ecma-array-object.h +++ b/jerry-core/ecma/operations/ecma-array-object.h @@ -80,12 +80,8 @@ ecma_value_t *ecma_fast_array_extend (ecma_object_t *object_p, uint32_t new_leng bool ecma_fast_array_set_property (ecma_object_t *object_p, uint32_t index, ecma_value_t value); -bool ecma_array_object_delete_property (ecma_object_t *object_p, ecma_string_t *property_name_p); - uint32_t ecma_delete_fast_array_properties (ecma_object_t *object_p, uint32_t new_length); -ecma_collection_t *ecma_fast_array_object_own_property_keys (ecma_object_t *object_p, jerry_property_filter_t filter); - void ecma_fast_array_convert_to_normal (ecma_object_t *object_p); #if JERRY_ESNEXT @@ -94,16 +90,72 @@ ecma_object_t *ecma_op_array_species_create (ecma_object_t *original_array_p, ec ecma_value_t ecma_op_create_array_iterator (ecma_object_t *obj_p, ecma_iterator_kind_t kind); #endif /* JERRY_ESNEXT */ -ecma_value_t ecma_op_array_object_set_length (ecma_object_t *object_p, ecma_value_t new_value, uint16_t flags); - -ecma_value_t ecma_op_array_object_define_own_property (ecma_object_t *object_p, - ecma_string_t *property_name_p, - const ecma_property_descriptor_t *property_desc_p); +ecma_value_t ecma_op_array_object_set_length (ecma_object_t *object_p, ecma_value_t new_value, uint32_t flags); uint32_t ecma_array_get_length (ecma_object_t *array_p); ecma_value_t ecma_array_object_to_string (ecma_value_t this_arg); +ecma_property_descriptor_t ecma_array_object_get_own_property (ecma_object_t *obj_p, ecma_string_t *property_name_p); +ecma_value_t ecma_array_object_define_own_property (ecma_object_t *object_p, + ecma_string_t *property_name_p, + const ecma_property_descriptor_t *property_desc_p); +void ecma_array_object_list_lazy_property_keys (ecma_object_t *obj_p, + ecma_collection_t *prop_names_p, + ecma_property_counter_t *prop_counter_p, + jerry_property_filter_t filter); +ecma_value_t ecma_array_object_get (ecma_object_t *obj_p, ecma_string_t *property_name_p, ecma_value_t receiver); +ecma_value_t ecma_array_object_set (ecma_object_t *obj_p, + ecma_string_t *property_name_p, + ecma_value_t value, + ecma_value_t receiver, + bool is_throw); +ecma_value_t ecma_array_object_delete (ecma_object_t *obj_p, ecma_string_t *property_name_p, bool is_throw); +ecma_collection_t *ecma_array_object_own_property_keys (ecma_object_t *object_p, jerry_property_filter_t filter); + +/** + * Virtual function table for array object's internal methods + */ +#define ECMA_ARRAY_OBJ_VTABLE \ + [ECMA_OBJECT_TYPE_ARRAY] = { ecma_ordinary_object_get_prototype_of, \ + ecma_ordinary_object_set_prototype_of, \ + ecma_ordinary_object_is_extensible, \ + ecma_ordinary_object_prevent_extensions, \ + ecma_array_object_get_own_property, \ + ecma_array_object_define_own_property, \ + ecma_ordinary_object_has_property, \ + ecma_array_object_get, \ + ecma_array_object_set, \ + ecma_array_object_delete, \ + ecma_array_object_own_property_keys, \ + ecma_ordinary_object_call, \ + ecma_ordinary_object_construct, \ + ecma_array_object_list_lazy_property_keys, \ + ecma_ordinary_object_delete_lazy_property } + +ecma_property_descriptor_t ecma_builtin_array_object_get_own_property (ecma_object_t *obj_p, + ecma_string_t *property_name_p); + +/** + * Virtual function table for built-in array object's internal methods + */ +#define ECMA_BUILT_IN_ARRAY_OBJ_VTABLE \ + [ECMA_OBJECT_TYPE_BUILT_IN_ARRAY] = { ecma_ordinary_object_get_prototype_of, \ + ecma_ordinary_object_set_prototype_of, \ + ecma_ordinary_object_is_extensible, \ + ecma_ordinary_object_prevent_extensions, \ + ecma_builtin_array_object_get_own_property, \ + ecma_array_object_define_own_property, \ + ecma_ordinary_object_has_property, \ + ecma_array_object_get, \ + ecma_array_object_set, \ + ecma_ordinary_object_delete, \ + ecma_ordinary_object_own_property_keys, \ + ecma_ordinary_object_call, \ + ecma_ordinary_object_construct, \ + ecma_builtin_object_list_lazy_property_keys, \ + ecma_builtin_object_delete_lazy_property } + /** * @} * @} diff --git a/jerry-core/ecma/operations/ecma-arraybuffer-object.c b/jerry-core/ecma/operations/ecma-arraybuffer-object.c index 3a436d1f80..2e88e77081 100644 --- a/jerry-core/ecma/operations/ecma-arraybuffer-object.c +++ b/jerry-core/ecma/operations/ecma-arraybuffer-object.c @@ -475,7 +475,7 @@ ecma_builtin_arraybuffer_slice (ecma_value_t this_arg, const ecma_value_t *argum ecma_object_t *ctor_obj_p = ecma_get_object_from_value (ctor); ecma_value_t new_len_value = ecma_make_uint32_value (new_len); - ecma_value_t new_arraybuffer = ecma_op_function_construct (ctor_obj_p, ctor_obj_p, &new_len_value, 1); + ecma_value_t new_arraybuffer = ecma_internal_method_construct (ctor_obj_p, ctor_obj_p, &new_len_value, 1); ecma_deref_object (ctor_obj_p); ecma_free_value (new_len_value); diff --git a/jerry-core/ecma/operations/ecma-async-generator-object.c b/jerry-core/ecma/operations/ecma-async-generator-object.c index f40dc5b17f..1ff9190420 100644 --- a/jerry-core/ecma/operations/ecma-async-generator-object.c +++ b/jerry-core/ecma/operations/ecma-async-generator-object.c @@ -107,11 +107,11 @@ ecma_async_yield_call (ecma_value_t function, /**< function (takes reference) */ if (argument == ECMA_VALUE_EMPTY) { - result = ecma_op_function_validated_call (function, iterator, NULL, 0); + result = ecma_internal_method_validated_call (function, iterator, NULL, 0); } else { - result = ecma_op_function_validated_call (function, iterator, &argument, 1); + result = ecma_internal_method_validated_call (function, iterator, &argument, 1); } ecma_free_value (function); diff --git a/jerry-core/ecma/operations/ecma-bound-function.c b/jerry-core/ecma/operations/ecma-bound-function.c new file mode 100644 index 0000000000..53d5bee365 --- /dev/null +++ b/jerry-core/ecma/operations/ecma-bound-function.c @@ -0,0 +1,303 @@ +/* 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-bound-function.h" + +#include "ecma-builtins.h" +#include "ecma-function-object.h" +#include "ecma-globals.h" +#include "ecma-objects.h" +#include "ecma-ordinary-object.h" + +#include "jcontext.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaboundfunctionobject ECMA bound function object related routines + * @{ + */ + +/** + * ecma bound function object's [[GetOwnProperty]] internal method + * + * @return ecma property descriptor t + */ +ecma_property_descriptor_t +ecma_bound_function_get_own_property (ecma_object_t *obj_p, /**< the object */ + ecma_string_t *property_name_p) /**< property name */ +{ + ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); + + prop_desc.u.property_p = ecma_find_named_property (obj_p, property_name_p); + + if (prop_desc.u.property_p != NULL) + { + prop_desc.flags = + ECMA_PROP_DESC_PROPERTY_FOUND | ECMA_PROPERTY_TO_PROPERTY_DESCRIPTOR_FLAGS (prop_desc.u.property_p); + return prop_desc; + } + + if (ecma_string_is_length (property_name_p)) + { + ecma_bound_function_t *bound_func_p = (ecma_bound_function_t *) obj_p; + ecma_value_t args_len_or_this = bound_func_p->header.u.bound_function.args_len_or_this; + ecma_number_t length = 0; + ecma_integer_value_t args_length = 1; + uint8_t length_attributes; + + if (ecma_is_value_integer_number (args_len_or_this)) + { + args_length = ecma_get_integer_from_value (args_len_or_this); + } + +#if JERRY_ESNEXT + if (ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (bound_func_p->header.u.bound_function.target_function)) + { + return prop_desc; + } + + prop_desc.flags = ECMA_PROP_DESC_PROPERTY_FOUND | ECMA_PROP_DESC_DATA_CONFIGURABLE; + length_attributes = ECMA_PROPERTY_BUILT_IN_CONFIGURABLE; + length = ecma_get_number_from_value (bound_func_p->target_length) - (args_length - 1); +#else /* !JERRY_ESNEXT */ + prop_desc.flags = ECMA_PROP_DESC_PROPERTY_FOUND | ECMA_PROP_DESC_DATA; + length_attributes = ECMA_PROPERTY_BUILT_IN_FIXED; + + ecma_object_t *target_func_p; + target_func_p = + ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, bound_func_p->header.u.bound_function.target_function); + + if (ecma_object_get_class_name (target_func_p) == LIT_MAGIC_STRING_FUNCTION_UL) + { + /* The property_name_p argument contains the 'length' string. */ + ecma_value_t get_len_value = + ecma_internal_method_get (target_func_p, property_name_p, ecma_make_object_value (target_func_p)); + + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (get_len_value)); + JERRY_ASSERT (ecma_is_value_integer_number (get_len_value)); + + length = (ecma_number_t) (ecma_get_integer_from_value (get_len_value) - (args_length - 1)); + } +#endif /* JERRY_ESNEXT */ + + if (length < 0) + { + length = 0; + } + + ecma_property_value_t *prop_value_p = + ecma_create_named_data_property (obj_p, property_name_p, length_attributes, &prop_desc.u.property_p); + prop_value_p->value = ecma_make_number_value (length); + return prop_desc; + } + +#if !JERRY_ESNEXT + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_CALLER) + || ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_ARGUMENTS)) + { + ecma_object_t *thrower_p = ecma_builtin_get (ECMA_BUILTIN_ID_TYPE_ERROR_THROWER); + + prop_desc.flags = ECMA_PROP_DESC_PROPERTY_FOUND; + /* The string_p argument contans the name. */ + ecma_create_named_accessor_property (obj_p, + property_name_p, + thrower_p, + thrower_p, + ECMA_PROPERTY_BUILT_IN_FIXED, + &prop_desc.u.property_p); + return prop_desc; + } +#endif /* !JERRY_ESNEXT */ + + return prop_desc; +} /* ecma_bound_function_get_own_property */ + +/** + * Append the bound arguments into the given collection + * + * Note: + * - The whole bound chain is resolved + * - The first element of the collection contains the bounded this value + * + * @return target function of the bound function + */ +JERRY_ATTR_NOINLINE static ecma_object_t * +ecma_op_bound_function_get_argument_list (ecma_object_t *func_obj_p, /**< bound bunction object */ + ecma_collection_t *list_p) /**< list of arguments */ +{ + JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION); + + ecma_bound_function_t *bound_func_p = (ecma_bound_function_t *) func_obj_p; + + func_obj_p = + ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, bound_func_p->header.u.bound_function.target_function); + + ecma_value_t args_len_or_this = bound_func_p->header.u.bound_function.args_len_or_this; + + uint32_t args_length = 1; + + if (ecma_is_value_integer_number (args_len_or_this)) + { + args_length = (uint32_t) ecma_get_integer_from_value (args_len_or_this); + } + + /* 5. */ + if (args_length != 1) + { + const ecma_value_t *args_p = (const ecma_value_t *) (bound_func_p + 1); + list_p->buffer_p[0] = *args_p; + + if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION) + { + func_obj_p = ecma_op_bound_function_get_argument_list (func_obj_p, list_p); + } + ecma_collection_append (list_p, args_p + 1, args_length - 1); + } + else + { + list_p->buffer_p[0] = args_len_or_this; + } + + return func_obj_p; +} /* ecma_op_bound_function_get_argument_list */ + +/** + * ecma bound function object's [[Call]] internal method + * + * @return ecma value t + */ +ecma_value_t +ecma_bound_function_call (ecma_object_t *func_obj_p, /**< Function object */ + ecma_value_t this_value, /**< this value */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< length of arguments list */ +{ + JERRY_UNUSED (this_value); + + JERRY_CONTEXT (status_flags) &= (uint32_t) ~ECMA_STATUS_DIRECT_EVAL; + + ecma_collection_t *bound_arg_list_p = ecma_new_collection (); + ecma_collection_push_back (bound_arg_list_p, ECMA_VALUE_EMPTY); + + ecma_object_t *target_obj_p = ecma_op_bound_function_get_argument_list (func_obj_p, bound_arg_list_p); + + ecma_collection_append (bound_arg_list_p, arguments_list_p, arguments_list_len); + + JERRY_ASSERT (!ecma_is_value_empty (bound_arg_list_p->buffer_p[0])); + + ecma_value_t ret_value = ecma_internal_method_call (target_obj_p, + bound_arg_list_p->buffer_p[0], + bound_arg_list_p->buffer_p + 1, + (uint32_t) (bound_arg_list_p->item_count - 1)); + + ecma_collection_destroy (bound_arg_list_p); + + return ret_value; +} /* ecma_bound_function_call */ + +/** + * ecma bound function object's [[Construct]] internal method + * + * @return ecma property descriptor t + */ +ecma_value_t +ecma_bound_function_construct (ecma_object_t *func_obj_p, /**< Function object */ + ecma_object_t *new_target_p, /**< new target */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< length of arguments list */ +{ + ecma_collection_t *bound_arg_list_p = ecma_new_collection (); + ecma_collection_push_back (bound_arg_list_p, ECMA_VALUE_EMPTY); + + ecma_object_t *target_obj_p = ecma_op_bound_function_get_argument_list (func_obj_p, bound_arg_list_p); + + ecma_collection_append (bound_arg_list_p, arguments_list_p, arguments_list_len); + + if (func_obj_p == new_target_p) + { + new_target_p = target_obj_p; + } + + ecma_value_t ret_value = ecma_internal_method_construct (target_obj_p, + new_target_p, + bound_arg_list_p->buffer_p + 1, + (uint32_t) (bound_arg_list_p->item_count - 1)); + + ecma_collection_destroy (bound_arg_list_p); + + return ret_value; +} /* ecma_bound_function_construct */ + +/** + * List lazy instantiated property names of bound function object + */ +void +ecma_bound_function_list_lazy_property_keys (ecma_object_t *object_p, /**< function object */ + ecma_collection_t *prop_names_p, /**< prop name collection */ + ecma_property_counter_t *prop_counter_p, /**< property counters */ + jerry_property_filter_t filter) /**< property name + * filter options */ +{ + if (filter & JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS) + { + return; + } + +#if JERRY_ESNEXT + /* Unintialized 'length' property is non-enumerable (ECMA-262 v6, 19.2.4.1) */ + ecma_bound_function_t *bound_func_p = (ecma_bound_function_t *) object_p; + if (!ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (bound_func_p->header.u.bound_function.target_function)) + { + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); + prop_counter_p->string_named_props++; + } +#else /* !JERRY_ESNEXT */ + JERRY_UNUSED (object_p); + /* 'length' property is non-enumerable (ECMA-262 v5, 13.2.5) */ + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); + prop_counter_p->string_named_props++; +#endif /* JERRY_ESNEXT */ + + /* 'caller' property is non-enumerable (ECMA-262 v5, 13.2.5) */ + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_CALLER)); + + /* 'arguments' property is non-enumerable (ECMA-262 v5, 13.2.5) */ + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_ARGUMENTS)); + + prop_counter_p->string_named_props += 2; +} /* ecma_bound_object_list_lazy_property_keys */ + +/** + * Delete configurable properties of bound functions. + */ +void +ecma_bound_function_delete_lazy_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *property_name_p) /**< property name */ +{ + JERRY_UNUSED (property_name_p); + + ecma_bound_function_t *bound_func_p = (ecma_bound_function_t *) object_p; + + JERRY_ASSERT (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_LENGTH)); + JERRY_ASSERT (!ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (bound_func_p->header.u.bound_function.target_function)); + + ECMA_SET_FIRST_BIT_TO_POINTER_TAG (bound_func_p->header.u.bound_function.target_function); +} /* ecma_bound_function_delete_lazy_property */ + +/** + * @} + * @} + */ diff --git a/jerry-core/ecma/operations/ecma-bound-function.h b/jerry-core/ecma/operations/ecma-bound-function.h new file mode 100644 index 0000000000..d3efcc21b1 --- /dev/null +++ b/jerry-core/ecma/operations/ecma-bound-function.h @@ -0,0 +1,68 @@ +/* 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. + */ + +#ifndef ECMA_OP_BOUND_FUNCTION_H +#define ECMA_OP_BOUND_FUNCTION_H + +#include "ecma-globals.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaboundfunctionobject ECMA bound function object related routines + * @{ + */ + +ecma_property_descriptor_t ecma_bound_function_get_own_property (ecma_object_t *obj_p, ecma_string_t *property_name_p); +ecma_value_t ecma_bound_function_call (ecma_object_t *func_obj_p, + ecma_value_t this_value, + const ecma_value_t *arguments_list_p, + uint32_t arguments_list_len); +ecma_value_t ecma_bound_function_construct (ecma_object_t *func_obj_p, + ecma_object_t *new_target_p, + const ecma_value_t *arguments_list_p, + uint32_t arguments_list_len); +void ecma_bound_function_list_lazy_property_keys (ecma_object_t *object_p, + ecma_collection_t *prop_names_p, + ecma_property_counter_t *prop_counter_p, + jerry_property_filter_t filter); +void ecma_bound_function_delete_lazy_property (ecma_object_t *object_p, ecma_string_t *property_name_p); + +/** + * Virtual function table for bound function object's internal methods + */ +#define ECMA_BOUND_FUNCTION_OBJ_VTABLE \ + [ECMA_OBJECT_TYPE_BOUND_FUNCTION] = { ecma_ordinary_object_get_prototype_of, \ + ecma_ordinary_object_set_prototype_of, \ + ecma_ordinary_object_is_extensible, \ + ecma_ordinary_object_prevent_extensions, \ + ecma_bound_function_get_own_property, \ + ecma_ordinary_object_define_own_property, \ + ecma_ordinary_object_has_property, \ + ecma_ordinary_object_get, \ + ecma_ordinary_object_set, \ + ecma_ordinary_object_delete, \ + ecma_ordinary_object_own_property_keys, \ + ecma_bound_function_call, \ + ecma_bound_function_construct, \ + ecma_bound_function_list_lazy_property_keys, \ + ecma_bound_function_delete_lazy_property } + +/** + * @} + * @} + */ + +#endif /* !ECMA_OP_BOUND_FUNCTION_H */ diff --git a/jerry-core/ecma/operations/ecma-class-object.c b/jerry-core/ecma/operations/ecma-class-object.c new file mode 100644 index 0000000000..5585a6bfbc --- /dev/null +++ b/jerry-core/ecma/operations/ecma-class-object.c @@ -0,0 +1,203 @@ +/* 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-class-object.h" + +#include "ecma-arguments-object.h" +#include "ecma-globals.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" +#include "ecma-ordinary-object.h" +#include "ecma-string-object.h" +#include "ecma-typedarray-object.h" + +#include "jcontext.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaclassobject ECMA Class object related routines + * @{ + */ + +/** + * Virtual internal method function table for class objects + */ +static const ecma_internal_method_table_t CLASS_OBJ_VTABLE[] = { +/* These objects require custom property resolving. */ +#if JERRY_BUILTIN_TYPEDARRAY + ECMA_TYPEDARRAY_OBJ_VTABLE, +#endif /* JERRY_BUILTIN_TYPEDARRAY */ +#if JERRY_MODULE_SYSTEM + ECMA_MODULE_NAMESPACE_OBJ_VTABLE, +#endif /* JERRY_MODULE_SYSTEM */ + ECMA_STRING_OBJ_VTABLE, + ECMA_ARGUMENTS_OBJ_VTABLE, +}; + +/** + * Resolve the virtual function table for the given class object + */ +#define ECMA_CLASS_OBJECT_RESOLVE_VTABLE(obj_p) \ + ((((ecma_extended_object_t *) (obj_p))->u.cls.type <= ECMA_OBJECT_CLASS_ARGUMENTS) \ + ? &CLASS_OBJ_VTABLE[((ecma_extended_object_t *) obj_p)->u.cls.type] \ + : &VTABLE_CONTAINER[ECMA_OBJECT_TYPE_GENERAL]) + +/** + * Helper function for calling the given class object's [[GetOwnProperty]] internal method + * + * @return ecma property descriptor + */ +ecma_property_descriptor_t +ecma_class_object_get_own_property (ecma_object_t *obj_p, /**< object */ + ecma_string_t *property_name_p) /**< property name */ +{ + uint8_t type = ((ecma_extended_object_t *) obj_p)->u.cls.type; + + if (type <= ECMA_OBJECT_CLASS_ARGUMENTS) + { + return (&CLASS_OBJ_VTABLE[type])->get_own_property (obj_p, property_name_p); + } + + return ecma_ordinary_object_get_own_property (obj_p, property_name_p); +} /* ecma_class_object_get_own_property */ + +/** + * Helper function for calling the given class object's [[DefineOwnProperty]] internal method + * + * @return ecma value + */ +ecma_value_t +ecma_class_object_define_own_property (ecma_object_t *obj_p, /**< object */ + ecma_string_t *property_name_p, /**< property name */ + const ecma_property_descriptor_t *property_desc_p) /**< property + * descriptor */ +{ + uint8_t type = ((ecma_extended_object_t *) obj_p)->u.cls.type; + + if (type <= ECMA_OBJECT_CLASS_ARGUMENTS) + { + return (&CLASS_OBJ_VTABLE[type])->define_own_property (obj_p, property_name_p, property_desc_p); + } + + return ecma_ordinary_object_define_own_property (obj_p, property_name_p, property_desc_p); +} /* ecma_class_object_define_own_property */ + +/** + * Helper function for calling the given class object's [[Get]] internal method + * + * @return ecma value + */ +ecma_value_t +ecma_class_object_get (ecma_object_t *obj_p, /**< object */ + ecma_string_t *property_name_p, /**< property name */ + ecma_value_t receiver) /**< receiver */ +{ + uint8_t type = ((ecma_extended_object_t *) obj_p)->u.cls.type; + + if (type <= ECMA_OBJECT_CLASS_ARGUMENTS) + { + return (&CLASS_OBJ_VTABLE[type])->get (obj_p, property_name_p, receiver); + } + + return ecma_ordinary_object_get (obj_p, property_name_p, receiver); +} /* ecma_class_object_get */ + +/** + * Helper function for calling the given class object's [[Set]] internal method + * + * @return ecma value + */ +ecma_value_t +ecma_class_object_set (ecma_object_t *obj_p, /**< object */ + ecma_string_t *property_name_p, /**< property name */ + ecma_value_t value, /**< ecma value */ + ecma_value_t receiver, /**< receiver */ + bool is_throw) /**< flag that controls failure handling */ +{ + uint8_t type = ((ecma_extended_object_t *) obj_p)->u.cls.type; + + if (type <= ECMA_OBJECT_CLASS_ARGUMENTS) + { + return (&CLASS_OBJ_VTABLE[type])->set (obj_p, property_name_p, value, receiver, is_throw); + } + + return ecma_ordinary_object_set (obj_p, property_name_p, value, receiver, is_throw); +} /* ecma_class_object_set */ + +/** + * Helper function for calling the given class object's [[Delete]] internal method + * + * @return ecma value + */ +ecma_value_t +ecma_class_object_delete_property (ecma_object_t *obj_p, /**< object */ + ecma_string_t *property_name_p, /**< property name */ + bool is_strict) /**< flag that controls failure handling */ +{ + uint8_t type = ((ecma_extended_object_t *) obj_p)->u.cls.type; + + if (type <= ECMA_OBJECT_CLASS_ARGUMENTS) + { + return (&CLASS_OBJ_VTABLE[type])->delete (obj_p, property_name_p, is_strict); + } + + return ecma_ordinary_object_delete (obj_p, property_name_p, is_strict); +} /* ecma_class_object_delete_property */ + +/** + * Helper function for calling the given class object's 'list lazy property keys' internal method + */ +void +ecma_class_object_list_lazy_property_keys (ecma_object_t *obj_p, /**< a built-in object */ + ecma_collection_t *prop_names_p, /**< prop name collection */ + ecma_property_counter_t *prop_counter_p, /**< property counters */ + jerry_property_filter_t filter) /**< name filters */ +{ + uint8_t type = ((ecma_extended_object_t *) obj_p)->u.cls.type; + + if (type <= ECMA_OBJECT_CLASS_ARGUMENTS) + { + (&CLASS_OBJ_VTABLE[type])->list_lazy_property_keys (obj_p, prop_names_p, prop_counter_p, filter); + } + else + { + ecma_ordinary_object_list_lazy_property_keys (obj_p, prop_names_p, prop_counter_p, filter); + } +} /* ecma_class_object_list_lazy_property_keys */ + +/** + * Helper function for calling the given class object's [[Delete]] internal method + */ +void +ecma_class_object_delete_lazy_property (ecma_object_t *obj_p, /**< object */ + ecma_string_t *property_name_p) /**< property name */ +{ + uint8_t type = ((ecma_extended_object_t *) obj_p)->u.cls.type; + + if (type <= ECMA_OBJECT_CLASS_ARGUMENTS) + { + CLASS_OBJ_VTABLE[type].delete_lazy_property (obj_p, property_name_p); + } + else + { + ecma_ordinary_object_delete_lazy_property (obj_p, property_name_p); + } +} /* ecma_class_object_delete_lazy_property */ + +/** + * @} + * @} + */ diff --git a/jerry-core/ecma/operations/ecma-class-object.h b/jerry-core/ecma/operations/ecma-class-object.h new file mode 100644 index 0000000000..63dd220782 --- /dev/null +++ b/jerry-core/ecma/operations/ecma-class-object.h @@ -0,0 +1,70 @@ +/* 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. + */ + +#ifndef ECMA_CLASS_OBJECT_H +#define ECMA_CLASS_OBJECT_H + +#include "ecma-globals.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaclassobject ECMA Class object related routines + * @{ + */ + +ecma_property_descriptor_t ecma_class_object_get_own_property (ecma_object_t *obj_p, ecma_string_t *property_name_p); +ecma_value_t ecma_class_object_define_own_property (ecma_object_t *obj_p, + ecma_string_t *property_name_p, + const ecma_property_descriptor_t *property_desc_p); +ecma_value_t ecma_class_object_get (ecma_object_t *obj_p, ecma_string_t *property_name_p, ecma_value_t receiver); +ecma_value_t ecma_class_object_set (ecma_object_t *obj_p, + ecma_string_t *property_name_p, + ecma_value_t value, + ecma_value_t receiver, + bool is_throw); +ecma_value_t ecma_class_object_delete_property (ecma_object_t *obj_p, ecma_string_t *property_name_p, bool is_strict); +void ecma_class_object_list_lazy_property_keys (ecma_object_t *object_p, + ecma_collection_t *prop_names_p, + ecma_property_counter_t *prop_counter_p, + jerry_property_filter_t filter); +void ecma_class_object_delete_lazy_property (ecma_object_t *obj_p, ecma_string_t *property_name_p); + +/** + * Virtual function table for Class object's internal methods + */ +#define ECMA_CLASS_OBJ_VTABLE \ + [ECMA_OBJECT_TYPE_CLASS] = { ecma_ordinary_object_get_prototype_of, \ + ecma_ordinary_object_set_prototype_of, \ + ecma_ordinary_object_is_extensible, \ + ecma_ordinary_object_prevent_extensions, \ + ecma_class_object_get_own_property, \ + ecma_class_object_define_own_property, \ + ecma_ordinary_object_has_property, \ + ecma_class_object_get, \ + ecma_class_object_set, \ + ecma_class_object_delete_property, \ + ecma_ordinary_object_own_property_keys, \ + ecma_ordinary_object_call, \ + ecma_ordinary_object_construct, \ + ecma_class_object_list_lazy_property_keys, \ + ecma_class_object_delete_lazy_property } + +/** + * @} + * @} + */ + +#endif /* ECMA_CLASS_OBJECT_H */ diff --git a/jerry-core/ecma/operations/ecma-constructor-function.c b/jerry-core/ecma/operations/ecma-constructor-function.c new file mode 100644 index 0000000000..cc85f25f49 --- /dev/null +++ b/jerry-core/ecma/operations/ecma-constructor-function.c @@ -0,0 +1,225 @@ +/* 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-constructor-function.h" + +#include "ecma-builtins.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-lex-env.h" +#include "ecma-objects.h" +#include "ecma-ordinary-object.h" + +#include "jcontext.h" +#include "opcodes.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaconstructorfunctionobject Ecma constructor function object related routines + * @{ + */ + +#if JERRY_ESNEXT +/** + * ecma class implicit constructor object's [[Call]] internal method + * + * @return ecma value + */ +ecma_value_t +ecma_constructor_function_call (ecma_object_t *func_obj_p, /**< Function object */ + ecma_value_t this_value, /**< new target */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< length of arguments list */ +{ + JERRY_UNUSED_4 (func_obj_p, this_value, arguments_list_p, arguments_list_len); + + return ecma_raise_type_error (ECMA_ERR_CLASS_CONSTRUCTOR_NEW); +} /* ecma_constructor_function_call */ + +/** + * ecma class implicit constructor object's [[Construct]] internal method + * + * @return ecma value + */ +ecma_value_t +ecma_constructor_function_construct (ecma_object_t *func_obj_p, /**< Function object */ + ecma_object_t *new_target_p, /**< new target */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< length of arguments list */ +{ + ecma_extended_object_t *constructor_object_p = (ecma_extended_object_t *) func_obj_p; + + if (!(constructor_object_p->u.constructor_function.flags & ECMA_CONSTRUCTOR_FUNCTION_HAS_HERITAGE)) + { + ecma_object_t *proto_p = ecma_op_get_prototype_from_constructor (new_target_p, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); + + if (JERRY_UNLIKELY (proto_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_object_t *new_this_object_p = ecma_create_object (proto_p, 0, ECMA_OBJECT_TYPE_GENERAL); + ecma_deref_object (proto_p); + + ecma_value_t new_this_value = ecma_make_object_value (new_this_object_p); + ecma_value_t ret_value = opfunc_init_class_fields (func_obj_p, new_this_value); + + if (ECMA_IS_VALUE_ERROR (ret_value)) + { + ecma_deref_object (new_this_object_p); + return ret_value; + } + + return new_this_value; + } + + ecma_value_t super_ctor = ecma_op_function_get_super_constructor (func_obj_p); + + if (ECMA_IS_VALUE_ERROR (super_ctor)) + { + return super_ctor; + } + + ecma_object_t *super_ctor_p = ecma_get_object_from_value (super_ctor); + ecma_value_t result = + ecma_internal_method_construct (super_ctor_p, new_target_p, arguments_list_p, arguments_list_len); + ecma_deref_object (super_ctor_p); + + if (ecma_is_value_object (result)) + { + ecma_value_t fields_value = opfunc_init_class_fields (func_obj_p, result); + + if (ECMA_IS_VALUE_ERROR (fields_value)) + { + ecma_free_value (result); + return fields_value; + } + } + + return result; +} /* ecma_constructor_function_construct */ + +/** + * Perform a JavaScript class function object method call. + * + * The input function object should be a JavaScript class constructor + * + * @return the result of the function call. + */ +ecma_value_t JERRY_ATTR_NOINLINE +ecma_function_object_construct_constructor (ecma_object_t *func_obj_p, /**< Function object */ + ecma_object_t *new_target_p, /**< new target */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< length of arguments list */ +{ + ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) func_obj_p; + ecma_object_t *scope_p = ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, ext_func_p->u.function.scope_cp); + const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p); + uint16_t status_flags = bytecode_data_p->status_flags; + + JERRY_ASSERT (CBC_FUNCTION_GET_TYPE (status_flags) == CBC_FUNCTION_CONSTRUCTOR); + + ecma_value_t this_value; + + if (ECMA_GET_THIRD_BIT_FROM_POINTER_TAG (ext_func_p->u.function.scope_cp)) + { + this_value = ECMA_VALUE_UNINITIALIZED; + } + else + { + ecma_object_t *proto_p = ecma_op_get_prototype_from_constructor (new_target_p, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); + + if (JERRY_UNLIKELY (proto_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_object_t *new_this_obj_p = ecma_create_object (proto_p, 0, ECMA_OBJECT_TYPE_GENERAL); + ecma_deref_object (proto_p); + this_value = ecma_make_object_value (new_this_obj_p); + } + + if (!(status_flags & CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED)) + { + scope_p = ecma_create_decl_lex_env (scope_p); + } + + ecma_op_create_environment_record (scope_p, this_value, func_obj_p); + + ecma_object_t *old_new_target_p = JERRY_CONTEXT (current_new_target_p); + JERRY_CONTEXT (current_new_target_p) = new_target_p; + +#if JERRY_BUILTIN_REALMS + ecma_global_object_t *realm_p = ecma_op_function_get_realm (bytecode_data_p); + ecma_global_object_t *saved_global_object_p = JERRY_CONTEXT (global_object_p); + JERRY_CONTEXT (global_object_p) = realm_p; +#endif /* !JERRY_BUILTIN_REALMS */ + + vm_frame_ctx_shared_args_t shared_args; + shared_args.header.status_flags = VM_FRAME_CTX_SHARED_HAS_ARG_LIST | VM_FRAME_CTX_SHARED_NON_ARROW_FUNC; + shared_args.header.function_object_p = func_obj_p; + shared_args.arg_list_p = arguments_list_p; + shared_args.arg_list_len = arguments_list_len; + shared_args.header.bytecode_header_p = bytecode_data_p; + + ecma_value_t result = vm_run (&shared_args.header, this_value, scope_p); + +#if JERRY_BUILTIN_REALMS + JERRY_CONTEXT (global_object_p) = saved_global_object_p; +#endif /* JERRY_BUILTIN_REALMS */ + + JERRY_CONTEXT (current_new_target_p) = old_new_target_p; + + /* ECMAScript v6, 9.2.2.13 */ + if (JERRY_UNLIKELY (this_value == ECMA_VALUE_UNINITIALIZED)) + { + if (!ECMA_IS_VALUE_ERROR (result) && !ecma_is_value_object (result)) + { + if (!ecma_is_value_undefined (result)) + { + ecma_free_value (result); + result = ecma_raise_type_error (ECMA_ERR_DERIVED_CTOR_RETURN_NOR_OBJECT_OR_UNDEFINED); + } + else + { + result = ecma_op_get_this_binding (scope_p); + } + } + } + + if (!(status_flags & CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED)) + { + ecma_deref_object (scope_p); + } + + if (ECMA_IS_VALUE_ERROR (result) || ecma_is_value_object (result)) + { + ecma_free_value (this_value); + return result; + } + + ecma_free_value (result); + return this_value; +} /* ecma_function_object_construct_constructor */ + +#endif /* JERRY_ESNEXT */ + +/** + * @} + * @} + */ diff --git a/jerry-core/ecma/operations/ecma-constructor-function.h b/jerry-core/ecma/operations/ecma-constructor-function.h new file mode 100644 index 0000000000..30fa534363 --- /dev/null +++ b/jerry-core/ecma/operations/ecma-constructor-function.h @@ -0,0 +1,69 @@ +/* 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. + */ + +#ifndef ECMA_OP_CONSTRUCTOR_FUNCTION_H +#define ECMA_OP_CONSTRUCTOR_FUNCTION_H + +#include "ecma-globals.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaconstructorfunctionobject Ecma constructor function object related routines + * @{ + */ + +#if JERRY_ESNEXT +ecma_value_t ecma_function_object_construct_constructor (ecma_object_t *func_obj_p, + ecma_object_t *new_target_p, + const ecma_value_t *arguments_list_p, + uint32_t arguments_list_len); + +ecma_value_t ecma_constructor_function_call (ecma_object_t *func_obj_p, + ecma_value_t this_value, + const ecma_value_t *arguments_list_p, + uint32_t arguments_list_len); +ecma_value_t ecma_constructor_function_construct (ecma_object_t *func_obj_p, + ecma_object_t *new_target_p, + const ecma_value_t *arguments_list_p, + uint32_t arguments_list_len); + +/** + * Virtual function table for class implicit constructor object's internal methods + */ +#define ECMA_CONSTRUCTOR_FUNCTION_OBJ_VTABLE \ + [ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION] = { ecma_ordinary_object_get_prototype_of, \ + ecma_ordinary_object_set_prototype_of, \ + ecma_ordinary_object_is_extensible, \ + ecma_ordinary_object_prevent_extensions, \ + ecma_ordinary_object_get_own_property, \ + ecma_ordinary_object_define_own_property, \ + ecma_ordinary_object_has_property, \ + ecma_ordinary_object_get, \ + ecma_ordinary_object_set, \ + ecma_ordinary_object_delete, \ + ecma_ordinary_object_own_property_keys, \ + ecma_constructor_function_call, \ + ecma_constructor_function_construct, \ + ecma_ordinary_object_list_lazy_property_keys, \ + ecma_ordinary_object_delete_lazy_property } +#endif /* JERRY_ESNEXT */ + +/** + * @} + * @} + */ + +#endif /* !ECMA_OP_CONSTRUCTOR_FUNCTION_H */ diff --git a/jerry-core/ecma/operations/ecma-container-object.c b/jerry-core/ecma/operations/ecma-container-object.c index f975c39a92..1189b7b2a3 100644 --- a/jerry-core/ecma/operations/ecma-container-object.c +++ b/jerry-core/ecma/operations/ecma-container-object.c @@ -459,7 +459,7 @@ ecma_op_container_create (const ecma_value_t *arguments_list_p, /**< arguments l const ecma_value_t value = result; ecma_value_t arguments[] = { value }; - result = ecma_op_function_call (adder_func_p, set_value, arguments, 1); + result = ecma_internal_method_call (adder_func_p, set_value, arguments, 1); ecma_free_value (value); } @@ -499,7 +499,7 @@ ecma_op_container_create (const ecma_value_t *arguments_list_p, /**< arguments l const ecma_value_t value = result; ecma_value_t arguments[] = { key, value }; - result = ecma_op_function_call (adder_func_p, set_value, arguments, 2); + result = ecma_internal_method_call (adder_func_p, set_value, arguments, 2); ecma_free_value (key); ecma_free_value (value); @@ -745,7 +745,7 @@ ecma_op_container_foreach (ecma_extended_object_t *map_object_p, /**< map object ecma_value_t this_arg = ecma_make_object_value ((ecma_object_t *) map_object_p); ecma_value_t call_args[] = { value_arg, key_arg, this_arg }; - ecma_value_t call_value = ecma_op_function_call (func_object_p, predicate_this_arg, call_args, 3); + ecma_value_t call_value = ecma_internal_method_call (func_object_p, predicate_this_arg, call_args, 3); if (ECMA_IS_VALUE_ERROR (call_value)) { diff --git a/jerry-core/ecma/operations/ecma-conversion.c b/jerry-core/ecma/operations/ecma-conversion.c index 9a71b2ff60..d00269438d 100644 --- a/jerry-core/ecma/operations/ecma-conversion.c +++ b/jerry-core/ecma/operations/ecma-conversion.c @@ -602,7 +602,7 @@ ecma_op_from_property_descriptor (const ecma_property_descriptor_t *src_prop_des ecma_object_t *obj_p = ecma_op_create_object_object_noarg (); ecma_value_t completion; - ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); + ecma_property_descriptor_t prop_desc = ecma_make_empty_define_property_descriptor (); { prop_desc.flags = (JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_WRITABLE_DEFINED | JERRY_PROP_IS_WRITABLE | JERRY_PROP_IS_ENUMERABLE_DEFINED | JERRY_PROP_IS_ENUMERABLE @@ -618,14 +618,15 @@ ecma_op_from_property_descriptor (const ecma_property_descriptor_t *src_prop_des /* a. */ prop_desc.value = src_prop_desc_p->value; - completion = ecma_op_object_define_own_property (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_VALUE), &prop_desc); + completion = + ecma_internal_method_define_own_property (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_VALUE), &prop_desc); JERRY_ASSERT (ecma_is_value_true (completion)); /* b. */ prop_desc.value = ecma_make_boolean_value (src_prop_desc_p->flags & JERRY_PROP_IS_WRITABLE); completion = - ecma_op_object_define_own_property (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_WRITABLE), &prop_desc); + ecma_internal_method_define_own_property (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_WRITABLE), &prop_desc); JERRY_ASSERT (ecma_is_value_true (completion)); } else @@ -637,29 +638,15 @@ ecma_op_from_property_descriptor (const ecma_property_descriptor_t *src_prop_des #endif /* JERRY_ESNEXT */ { /* a. */ - if (src_prop_desc_p->get_p == NULL) - { - prop_desc.value = ECMA_VALUE_UNDEFINED; - } - else - { - prop_desc.value = ecma_make_object_value (src_prop_desc_p->get_p); - } - - completion = ecma_op_object_define_own_property (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_GET), &prop_desc); + prop_desc.value = src_prop_desc_p->u.accessor.get; + completion = + ecma_internal_method_define_own_property (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_GET), &prop_desc); JERRY_ASSERT (ecma_is_value_true (completion)); /* b. */ - if (src_prop_desc_p->set_p == NULL) - { - prop_desc.value = ECMA_VALUE_UNDEFINED; - } - else - { - prop_desc.value = ecma_make_object_value (src_prop_desc_p->set_p); - } - - completion = ecma_op_object_define_own_property (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_SET), &prop_desc); + prop_desc.value = src_prop_desc_p->u.accessor.set; + completion = + ecma_internal_method_define_own_property (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_SET), &prop_desc); JERRY_ASSERT (ecma_is_value_true (completion)); } } @@ -667,18 +654,100 @@ ecma_op_from_property_descriptor (const ecma_property_descriptor_t *src_prop_des prop_desc.value = ecma_make_boolean_value (src_prop_desc_p->flags & JERRY_PROP_IS_ENUMERABLE); completion = - ecma_op_object_define_own_property (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_ENUMERABLE), &prop_desc); + ecma_internal_method_define_own_property (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_ENUMERABLE), &prop_desc); JERRY_ASSERT (ecma_is_value_true (completion)); prop_desc.value = ecma_make_boolean_value (src_prop_desc_p->flags & JERRY_PROP_IS_CONFIGURABLE); completion = - ecma_op_object_define_own_property (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_CONFIGURABLE), &prop_desc); + ecma_internal_method_define_own_property (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_CONFIGURABLE), &prop_desc); JERRY_ASSERT (ecma_is_value_true (completion)); return obj_p; } /* ecma_op_from_property_descriptor */ +/** + * Function to create an object from a property descriptor + * + * @return constructed object + */ +ecma_object_t * +ecma_op_create_object_from_property_descriptor ( + const ecma_property_descriptor_t *prop_desc_p) /**< property descriptor */ +{ + ecma_object_t *obj_p = ecma_op_create_object_object_noarg (); + + if (ecma_property_descriptor_is_data_descriptor (prop_desc_p)) + { + ecma_property_value_t *value = ecma_create_named_data_property (obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_VALUE), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, + NULL); + + value->value = ecma_copy_value_if_not_object (ecma_property_descriptor_value (prop_desc_p)); + + ecma_property_value_t *writable = + ecma_create_named_data_property (obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_WRITABLE), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, + NULL); + + writable->value = ecma_make_boolean_value (ecma_property_descriptor_is_writable (prop_desc_p)); + } + else + { + ecma_property_value_t *getter = ecma_create_named_data_property (obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_GET), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, + NULL); + + ecma_object_t *prop_desc_getter = ecma_property_descriptor_accessor_getter (prop_desc_p); + + if (prop_desc_getter == NULL) + { + getter->value = ECMA_VALUE_UNDEFINED; + } + else + { + getter->value = ecma_make_object_value (prop_desc_getter); + } + + ecma_property_value_t *setter = ecma_create_named_data_property (obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_SET), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, + NULL); + + ecma_object_t *prop_desc_setter = ecma_property_descriptor_accessor_setter (prop_desc_p); + + if (prop_desc_setter == NULL) + { + setter->value = ECMA_VALUE_UNDEFINED; + } + else + { + setter->value = ecma_make_object_value (prop_desc_setter); + } + } + + ecma_property_value_t *enumerable = + ecma_create_named_data_property (obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_ENUMERABLE), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, + NULL); + + enumerable->value = ecma_make_boolean_value (ecma_property_descriptor_is_enumerable (prop_desc_p)); + + ecma_property_value_t *configurable = + ecma_create_named_data_property (obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_CONFIGURABLE), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, + NULL); + + configurable->value = ecma_make_boolean_value (ecma_property_descriptor_is_configurable (prop_desc_p)); + + return obj_p; +} /* ecma_op_create_object_from_property_descriptor */ + /** * ToPropertyDescriptor operation. * @@ -703,7 +772,8 @@ ecma_op_to_property_descriptor (ecma_value_t obj_value, /**< object value */ ecma_value_t ret_value = ECMA_VALUE_ERROR; /* 3. */ - ecma_value_t enumerable_prop_value = ecma_op_object_find (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_ENUMERABLE)); + ecma_value_t enumerable_prop_value = + ecma_op_object_find (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_ENUMERABLE), obj_value); if (ECMA_IS_VALUE_ERROR (enumerable_prop_value)) { @@ -711,7 +781,7 @@ ecma_op_to_property_descriptor (ecma_value_t obj_value, /**< object value */ } /* 2. */ - ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); + ecma_property_descriptor_t prop_desc = ecma_make_empty_define_property_descriptor (); if (ecma_is_value_found (enumerable_prop_value)) { @@ -725,7 +795,7 @@ ecma_op_to_property_descriptor (ecma_value_t obj_value, /**< object value */ /* 4. */ ecma_value_t configurable_prop_value = - ecma_op_object_find (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_CONFIGURABLE)); + ecma_op_object_find (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_CONFIGURABLE), obj_value); if (ECMA_IS_VALUE_ERROR (configurable_prop_value)) { @@ -743,7 +813,8 @@ ecma_op_to_property_descriptor (ecma_value_t obj_value, /**< object value */ } /* 5. */ - ecma_value_t value_prop_value = ecma_op_object_find (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_VALUE)); + ecma_value_t value_prop_value = + ecma_op_object_find (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_VALUE), obj_value); if (ECMA_IS_VALUE_ERROR (value_prop_value)) { @@ -758,7 +829,8 @@ ecma_op_to_property_descriptor (ecma_value_t obj_value, /**< object value */ } /* 6. */ - ecma_value_t writable_prop_value = ecma_op_object_find (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_WRITABLE)); + ecma_value_t writable_prop_value = + ecma_op_object_find (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_WRITABLE), obj_value); if (ECMA_IS_VALUE_ERROR (writable_prop_value)) { @@ -775,7 +847,7 @@ ecma_op_to_property_descriptor (ecma_value_t obj_value, /**< object value */ } /* 7. */ - ecma_value_t get_prop_value = ecma_op_object_find (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_GET)); + ecma_value_t get_prop_value = ecma_op_object_find (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_GET), obj_value); if (ECMA_IS_VALUE_ERROR (get_prop_value)) { @@ -792,26 +864,11 @@ ecma_op_to_property_descriptor (ecma_value_t obj_value, /**< object value */ } prop_desc.flags |= JERRY_PROP_IS_GET_DEFINED; - - if (ecma_is_value_undefined (get_prop_value)) - { - prop_desc.get_p = NULL; - } - else - { - JERRY_ASSERT (ecma_is_value_object (get_prop_value)); - - ecma_object_t *get_p = ecma_get_object_from_value (get_prop_value); - ecma_ref_object (get_p); - - prop_desc.get_p = get_p; - } - - ecma_free_value (get_prop_value); + prop_desc.u.accessor.get = get_prop_value; } /* 8. */ - ecma_value_t set_prop_value = ecma_op_object_find (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_SET)); + ecma_value_t set_prop_value = ecma_op_object_find (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_SET), obj_value); if (ECMA_IS_VALUE_ERROR (set_prop_value)) { @@ -828,22 +885,7 @@ ecma_op_to_property_descriptor (ecma_value_t obj_value, /**< object value */ } prop_desc.flags |= JERRY_PROP_IS_SET_DEFINED; - - if (ecma_is_value_undefined (set_prop_value)) - { - prop_desc.set_p = NULL; - } - else - { - JERRY_ASSERT (ecma_is_value_object (set_prop_value)); - - ecma_object_t *set_p = ecma_get_object_from_value (set_prop_value); - ecma_ref_object (set_p); - - prop_desc.set_p = set_p; - } - - ecma_free_value (set_prop_value); + prop_desc.u.accessor.set = set_prop_value; } /* 9. */ @@ -861,7 +903,7 @@ ecma_op_to_property_descriptor (ecma_value_t obj_value, /**< object value */ free_desc: if (ECMA_IS_VALUE_ERROR (ret_value)) { - ecma_free_property_descriptor (&prop_desc); + ecma_free_define_property_descriptor (&prop_desc); } return ret_value; diff --git a/jerry-core/ecma/operations/ecma-conversion.h b/jerry-core/ecma/operations/ecma-conversion.h index 559b855208..42528e9137 100644 --- a/jerry-core/ecma/operations/ecma-conversion.h +++ b/jerry-core/ecma/operations/ecma-conversion.h @@ -69,6 +69,7 @@ ecma_collection_t *ecma_op_create_list_from_array_like (ecma_value_t arr, bool p ecma_object_t *ecma_op_from_property_descriptor (const ecma_property_descriptor_t *src_prop_desc_p); ecma_value_t ecma_op_to_property_descriptor (ecma_value_t obj_value, ecma_property_descriptor_t *out_prop_desc_p); +ecma_object_t *ecma_op_create_object_from_property_descriptor (const ecma_property_descriptor_t *prop_desc_p); /** * @} diff --git a/jerry-core/ecma/operations/ecma-function-object.c b/jerry-core/ecma/operations/ecma-function-object.c index 243e31ad42..8c8c1601f1 100644 --- a/jerry-core/ecma/operations/ecma-function-object.c +++ b/jerry-core/ecma/operations/ecma-function-object.c @@ -18,6 +18,7 @@ #include "ecma-alloc.h" #include "ecma-builtin-handlers.h" #include "ecma-builtin-helpers.h" +#include "ecma-constructor-function.h" #include "ecma-errors.h" #include "ecma-exceptions.h" #include "ecma-extended-info.h" @@ -26,6 +27,7 @@ #include "ecma-lex-env.h" #include "ecma-objects-general.h" #include "ecma-objects.h" +#include "ecma-ordinary-object.h" #include "ecma-promise-object.h" #include "ecma-proxy-object.h" #include "ecma-symbol-object.h" @@ -126,13 +128,13 @@ ecma_op_object_is_callable (ecma_object_t *obj_p) /**< ecma object */ const ecma_object_type_t type = ecma_get_object_type (obj_p); #if JERRY_BUILTIN_PROXY - if (ECMA_OBJECT_TYPE_IS_PROXY (type)) + if (JERRY_UNLIKELY (type == ECMA_OBJECT_TYPE_PROXY)) { return ecma_op_proxy_object_is_callable (obj_p); } #endif /* JERRY_BUILTIN_PROXY */ - return type >= ECMA_OBJECT_TYPE_FUNCTION; + return type >= ECMA_OBJECT_TYPE_FUNCTION && type <= ECMA_OBJECT_TYPE_NATIVE_FUNCTION; } /* ecma_op_object_is_callable */ /** @@ -163,8 +165,20 @@ ecma_object_check_constructor (ecma_object_t *obj_p) /**< ecma object */ ecma_object_type_t type = ecma_get_object_type (obj_p); - if (JERRY_UNLIKELY (type < ECMA_OBJECT_TYPE_PROXY)) + if (JERRY_UNLIKELY (type < ECMA_OBJECT_TYPE_FUNCTION || type > ECMA_OBJECT_TYPE_NATIVE_FUNCTION)) { +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_TYPE_IS_PROXY (type)) + { + if (!(obj_p->u2.prototype_cp & ECMA_PROXY_IS_CONSTRUCTABLE)) + { + return ECMA_ERR_PROXY_TARGET_IS_NOT_A_CONSTRUCTOR; + } + + return ECMA_IS_VALID_CONSTRUCTOR; + } +#endif /* JERRY_BUILTIN_PROXY */ + return ECMA_ERR_INVALID_TYPE_FOR_CONSTRUCTOR_CALL; } @@ -231,18 +245,6 @@ ecma_object_check_constructor (ecma_object_t *obj_p) /**< ecma object */ return ECMA_IS_VALID_CONSTRUCTOR; } -#if JERRY_BUILTIN_PROXY - if (ECMA_OBJECT_TYPE_IS_PROXY (type)) - { - if (!(obj_p->u2.prototype_cp & ECMA_PROXY_IS_CONSTRUCTABLE)) - { - return ECMA_ERR_PROXY_TARGET_IS_NOT_A_CONSTRUCTOR; - } - - return ECMA_IS_VALID_CONSTRUCTOR; - } -#endif /* JERRY_BUILTIN_PROXY */ - JERRY_ASSERT (type == ECMA_OBJECT_TYPE_NATIVE_FUNCTION || type == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION || type == ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION); @@ -700,35 +702,6 @@ ecma_op_create_external_function_object (ecma_native_handler_t handler_cb) /**< return function_obj_p; } /* ecma_op_create_external_function_object */ -#if JERRY_ESNEXT - -/** - * Create built-in native handler object. - * - * @return pointer to newly created native handler object - */ -ecma_object_t * -ecma_op_create_native_handler (ecma_native_handler_id_t id, /**< handler id */ - size_t object_size) /**< created object size */ -{ - ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE); - - ecma_object_t *function_obj_p = ecma_create_object (prototype_obj_p, object_size, ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION); - - ecma_extended_object_t *ext_func_obj_p = (ecma_extended_object_t *) function_obj_p; - ext_func_obj_p->u.built_in.id = ECMA_BUILTIN_ID_HANDLER; - ext_func_obj_p->u.built_in.routine_id = (uint8_t) id; - ext_func_obj_p->u.built_in.u2.routine_flags = ECMA_NATIVE_HANDLER_FLAGS_NONE; - -#if JERRY_BUILTIN_REALMS - ECMA_SET_INTERNAL_VALUE_POINTER (ext_func_obj_p->u.built_in.realm_value, ecma_builtin_get_global ()); -#endif /* JERRY_BUILTIN_REALMS */ - - return function_obj_p; -} /* ecma_op_create_native_handler */ - -#endif /* JERRY_ESNEXT */ - /** * Get compiled code of a function object. * @@ -905,7 +878,7 @@ ecma_op_function_has_instance (ecma_object_t *func_obj_p, /**< Function object * while (true) { - ecma_object_t *current_proto_p = ecma_op_object_get_prototype_of (v_obj_p); + ecma_object_t *current_proto_p = ecma_internal_method_get_prototype_of (v_obj_p); ecma_deref_object (v_obj_p); if (current_proto_p == NULL) @@ -948,7 +921,7 @@ ecma_op_function_has_instance (ecma_object_t *func_obj_p, /**< Function object * ecma_value_t ecma_op_function_get_super_constructor (ecma_object_t *func_obj_p) /**< function object */ { - ecma_object_t *super_ctor_p = ecma_op_object_get_prototype_of (func_obj_p); + ecma_object_t *super_ctor_p = ecma_internal_method_get_prototype_of (func_obj_p); if (JERRY_UNLIKELY (super_ctor_p == ECMA_OBJECT_POINTER_ERROR)) { @@ -1024,100 +997,285 @@ ecma_op_get_prototype_from_constructor (ecma_object_t *ctor_obj_p, /**< construc return proto_obj_p; } /* ecma_op_get_prototype_from_constructor */ -#if JERRY_ESNEXT /** - * Perform a JavaScript class function object method call. + * ecma function object's [[GetOwnProperty]] internal method * - * The input function object should be a JavaScript class constructor - * - * @return the result of the function call. + * @return ecma property descriptor t */ -static ecma_value_t JERRY_ATTR_NOINLINE -ecma_op_function_call_constructor (vm_frame_ctx_shared_args_t *shared_args_p, /**< shared data */ - ecma_object_t *scope_p, /**< lexical environment to use */ - ecma_value_t this_binding) /**< value of 'ThisBinding' */ +ecma_property_descriptor_t +ecma_function_object_get_own_property (ecma_object_t *obj_p, /**< the object */ + ecma_string_t *property_name_p) /**< property name */ { - shared_args_p->header.status_flags |= VM_FRAME_CTX_SHARED_NON_ARROW_FUNC; + ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); - ecma_value_t ret_value; + prop_desc.u.property_p = ecma_find_named_property (obj_p, property_name_p); - if (JERRY_CONTEXT (current_new_target_p) == NULL) + if (prop_desc.u.property_p != NULL) { - ret_value = ecma_raise_type_error (ECMA_ERR_CLASS_CONSTRUCTOR_REQUIRES_NEW); - goto exit; + prop_desc.flags = + ECMA_PROP_DESC_PROPERTY_FOUND | ECMA_PROPERTY_TO_PROPERTY_DESCRIPTOR_FLAGS (prop_desc.u.property_p); + return prop_desc; } - ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) shared_args_p->header.function_object_p; - if (ECMA_GET_THIRD_BIT_FROM_POINTER_TAG (ext_func_p->u.function.scope_cp)) + ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) obj_p; + + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_LENGTH)) { - this_binding = ECMA_VALUE_UNINITIALIZED; + if (ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (ext_func_p->u.function.scope_cp)) + { + return prop_desc; + } + + /* Initialize 'length' property */ + 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; + } + +#if !JERRY_ESNEXT + prop_desc.flags = ECMA_PROP_DESC_VIRTUAL_FOUND; + prop_desc.value = ecma_make_uint32_value (len); +#else /* JERRY_ESNEXT */ + if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_HAS_EXTENDED_INFO) + { + uint8_t *extended_info_p = ecma_compiled_code_resolve_extended_info (bytecode_data_p); + + if (*extended_info_p & CBC_EXTENDED_CODE_FLAGS_HAS_ARGUMENT_LENGTH) + { + len = ecma_extended_info_decode_vlq (&extended_info_p); + } + } + + prop_desc.flags = ECMA_PROP_DESC_PROPERTY_FOUND | ECMA_PROP_DESC_DATA_CONFIGURABLE; + ecma_property_value_t *value_p = ecma_create_named_data_property (obj_p, + property_name_p, + ECMA_PROPERTY_BUILT_IN_CONFIGURABLE, + &prop_desc.u.property_p); + value_p->value = ecma_make_uint32_value (len); +#endif /* !JERRY_ESNEXT */ + + return prop_desc; } - ecma_op_create_environment_record (scope_p, this_binding, shared_args_p->header.function_object_p); +#if JERRY_ESNEXT + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_NAME)) + { + if (ECMA_GET_SECOND_BIT_FROM_POINTER_TAG (ext_func_p->u.function.scope_cp)) + { + return prop_desc; + } + + const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p); + + if (CBC_FUNCTION_GET_TYPE (bytecode_data_p->status_flags) == CBC_FUNCTION_CONSTRUCTOR) + { + return prop_desc; + } + + ecma_value_t value = *ecma_compiled_code_resolve_function_name (bytecode_data_p); + JERRY_ASSERT (ecma_is_value_string (value)); + /* Initialize 'name' property */ + prop_desc.flags = ECMA_PROP_DESC_PROPERTY_FOUND | ECMA_PROP_DESC_DATA_CONFIGURABLE; + ecma_property_value_t *value_p = ecma_create_named_data_property (obj_p, + property_name_p, + ECMA_PROPERTY_BUILT_IN_CONFIGURABLE, + &prop_desc.u.property_p); + value_p->value = ecma_copy_value (value); + return prop_desc; + } +#endif /* JERRY_ESNEXT */ + + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_PROTOTYPE)) + { #if JERRY_BUILTIN_REALMS - ecma_global_object_t *saved_global_object_p = JERRY_CONTEXT (global_object_p); - JERRY_CONTEXT (global_object_p) = ecma_op_function_get_realm (shared_args_p->header.bytecode_header_p); + const ecma_compiled_code_t *byte_code_p = ecma_op_function_get_compiled_code (ext_func_p); + ecma_global_object_t *global_object_p = ecma_op_function_get_realm (byte_code_p); #endif /* JERRY_BUILTIN_REALMS */ - ret_value = vm_run (&shared_args_p->header, this_binding, scope_p); + ecma_builtin_id_t prototype_id = ECMA_BUILTIN_ID_OBJECT_PROTOTYPE; + +#if JERRY_ESNEXT + if (!CBC_FUNCTION_HAS_PROTOTYPE (byte_code_p->status_flags)) + { + return prop_desc; + } + + if (CBC_FUNCTION_GET_TYPE (byte_code_p->status_flags) == CBC_FUNCTION_GENERATOR) + { + prototype_id = ECMA_BUILTIN_ID_GENERATOR_PROTOTYPE; + } + else if (CBC_FUNCTION_GET_TYPE (byte_code_p->status_flags) == CBC_FUNCTION_ASYNC_GENERATOR) + { + prototype_id = ECMA_BUILTIN_ID_ASYNC_GENERATOR_PROTOTYPE; + } +#endif /* JERRY_ESNEXT */ #if JERRY_BUILTIN_REALMS - JERRY_CONTEXT (global_object_p) = saved_global_object_p; + ecma_object_t *prototype_p = ecma_builtin_get_from_realm (global_object_p, prototype_id); +#else /* !JERRY_BUILTIN_REALMS */ + ecma_object_t *prototype_p = ecma_builtin_get (prototype_id); #endif /* JERRY_BUILTIN_REALMS */ - /* ECMAScript v6, 9.2.2.13 */ - if (JERRY_UNLIKELY (this_binding == ECMA_VALUE_UNINITIALIZED)) + ecma_object_t *proto_object_p = ecma_create_object (prototype_p, 0, ECMA_OBJECT_TYPE_GENERAL); + +#if JERRY_ESNEXT + if (prototype_id == ECMA_BUILTIN_ID_OBJECT_PROTOTYPE) +#endif /* JERRY_ESNEXT */ + { + ecma_property_value_t *constructor_prop_value_p; + constructor_prop_value_p = ecma_create_named_data_property (proto_object_p, + ecma_get_magic_string (LIT_MAGIC_STRING_CONSTRUCTOR), + ECMA_PROPERTY_CONFIGURABLE_WRITABLE, + NULL); + + constructor_prop_value_p->value = ecma_make_object_value (obj_p); + } + + prop_desc.flags = ECMA_PROP_DESC_PROPERTY_FOUND | ECMA_PROP_DESC_DATA_WRITABLE; + ecma_property_value_t *prototype_prop_value_p; + prototype_prop_value_p = ecma_create_named_data_property (obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_PROTOTYPE), + ECMA_PROPERTY_BUILT_IN_WRITABLE, + &prop_desc.u.property_p); + + prototype_prop_value_p->value = ecma_make_object_value (proto_object_p); + ecma_deref_object (proto_object_p); + return prop_desc; + } + + const bool is_arguments = ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_ARGUMENTS); + + if (is_arguments || ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_CALLER)) { - if (!ECMA_IS_VALUE_ERROR (ret_value) && !ecma_is_value_object (ret_value)) + const ecma_compiled_code_t *bytecode_data_p; + bytecode_data_p = ecma_op_function_get_compiled_code ((ecma_extended_object_t *) obj_p); + +#if JERRY_ESNEXT + if (!(bytecode_data_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) + && CBC_FUNCTION_GET_TYPE (bytecode_data_p->status_flags) == CBC_FUNCTION_NORMAL) { - if (!ecma_is_value_undefined (ret_value)) - { - ecma_free_value (ret_value); - ret_value = ecma_raise_type_error (ECMA_ERR_DERIVED_CTOR_RETURN_NOR_OBJECT_OR_UNDEFINED); - } - else - { - ret_value = ecma_op_get_this_binding (scope_p); - } + prop_desc.flags = ECMA_PROP_DESC_PROPERTY_FOUND | ECMA_PROP_DESC_DATA; + ecma_property_value_t *value_p = + ecma_create_named_data_property (obj_p, property_name_p, ECMA_PROPERTY_BUILT_IN_FIXED, &prop_desc.u.property_p); + value_p->value = is_arguments ? ECMA_VALUE_NULL : ECMA_VALUE_UNDEFINED; + return prop_desc; + } +#else /* !JERRY_ESNEXT */ + if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) + { + ecma_object_t *thrower_p = ecma_builtin_get (ECMA_BUILTIN_ID_TYPE_ERROR_THROWER); + + prop_desc.flags = ECMA_PROP_DESC_PROPERTY_FOUND; + ecma_create_named_accessor_property (obj_p, + property_name_p, + thrower_p, + thrower_p, + ECMA_PROPERTY_BUILT_IN_FIXED, + &prop_desc.u.property_p); + return prop_desc; } +#endif /* JERRY_ESNEXT */ } -exit: - if (JERRY_UNLIKELY (shared_args_p->header.status_flags & VM_FRAME_CTX_SHARED_FREE_LOCAL_ENV)) + return prop_desc; +} /* ecma_function_object_get_own_property */ + +#if JERRY_ESNEXT +/** + * Set the 'new target' and 'this' for an arrow function object + * + * @return ecma value t + */ +static inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE +ecma_arrow_function_object_bind_this (ecma_object_t *func_obj_p, /**< shared data */ + ecma_object_t *scope_p) +{ + ecma_arrow_function_t *arrow_func_p = (ecma_arrow_function_t *) func_obj_p; + + if (ecma_is_value_undefined (arrow_func_p->new_target)) { - ecma_deref_object (scope_p); + JERRY_CONTEXT (current_new_target_p) = NULL; + } + else + { + JERRY_CONTEXT (current_new_target_p) = ecma_get_object_from_value (arrow_func_p->new_target); } - return ret_value; -} /* ecma_op_function_call_constructor */ + if (JERRY_UNLIKELY (arrow_func_p->this_binding == ECMA_VALUE_UNINITIALIZED)) + { + ecma_environment_record_t *env_record_p = ecma_op_get_environment_record (scope_p); + JERRY_ASSERT (env_record_p); + arrow_func_p->this_binding = env_record_p->this_binding; + } -#endif /* JERRY_ESNEXT */ + return arrow_func_p->this_binding; +} /* ecma_arrow_function_object_bind_this */ +#endif /* #JERRY_ESNEXT */ /** - * Perform a JavaScript function object method call. + * Get 'this' for a function object * - * The input function object should be a pure JavaScript method + * @return ecma value t + */ +static inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE +ecma_function_object_bind_this (vm_frame_ctx_shared_args_t *shared_args_p, /**< shared data */ + ecma_value_t this_value, /**< value of 'ThisBinding' */ + ecma_global_object_t *realm_p) /**< global object */ +{ + if (ecma_is_value_undefined (this_value) || ecma_is_value_null (this_value)) + { +#if JERRY_BUILTIN_REALMS + return realm_p->this_binding; +#else /* !JERRY_BUILTIN_REALMS */ + JERRY_UNUSED (realm_p); + return ecma_make_object_value (ecma_builtin_get_global ()); +#endif /* JERRY_BUILTIN_REALMS */ + } + + if (!ecma_is_value_object (this_value)) + { + shared_args_p->header.status_flags |= VM_FRAME_CTX_SHARED_FREE_THIS; + return ecma_op_to_object (this_value); + } + + return this_value; +} /* ecma_function_object_bind_this */ + +/** + * General [[Call]] implementation for function objects * - * @return the result of the function call. + * @return ecma value + * Returned value must be freed with ecma_free_value */ -static ecma_value_t -ecma_op_function_call_simple (ecma_object_t *func_obj_p, /**< Function object */ - ecma_value_t this_binding, /**< 'this' argument's value */ - const ecma_value_t *arguments_list_p, /**< arguments list */ - uint32_t arguments_list_len) /**< length of arguments list */ +ecma_value_t +ecma_function_object_call (ecma_object_t *func_obj_p, /**< Function object */ + ecma_value_t this_value, /**< 'this' argument's value */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< length of arguments list */ { - JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION); + JERRY_ASSERT (func_obj_p != NULL && !ecma_is_lexical_environment (func_obj_p)); vm_frame_ctx_shared_args_t shared_args; +#if JERRY_ESNEXT + shared_args.header.status_flags = VM_FRAME_CTX_SHARED_HAS_ARG_LIST | VM_FRAME_CTX_SHARED_NON_ARROW_FUNC; +#else /* !JERRY_ESNEXT */ shared_args.header.status_flags = VM_FRAME_CTX_SHARED_HAS_ARG_LIST; +#endif /* JERRY_ESNEXT */ shared_args.header.function_object_p = func_obj_p; shared_args.arg_list_p = arguments_list_p; shared_args.arg_list_len = arguments_list_len; - /* Entering Function Code (ECMA-262 v5, 10.4.3) */ ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) func_obj_p; - ecma_object_t *scope_p = ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, ext_func_p->u.function.scope_cp); /* 8. */ @@ -1126,16 +1284,16 @@ ecma_op_function_call_simple (ecma_object_t *func_obj_p, /**< Function object */ shared_args.header.bytecode_header_p = bytecode_data_p; -#if JERRY_BUILTIN_REALMS - ecma_global_object_t *realm_p = ecma_op_function_get_realm (bytecode_data_p); -#endif /* JERRY_BUILTIN_REALMS */ +#if JERRY_ESNEXT + ecma_object_t *old_new_target_p = JERRY_CONTEXT (current_new_target_p); +#endif /* JERRY_ESNEXT */ - /* 5. */ - if (!(status_flags & CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED)) - { - shared_args.header.status_flags |= VM_FRAME_CTX_SHARED_FREE_LOCAL_ENV; - scope_p = ecma_create_decl_lex_env (scope_p); - } +#if !JERRY_BUILTIN_REALMS + ecma_global_object_t *realm_p = NULL; +#else /* JERRY_BUILTIN_REALMS */ + ecma_global_object_t *realm_p = ecma_op_function_get_realm (bytecode_data_p); + ecma_global_object_t *saved_global_object_p = JERRY_CONTEXT (global_object_p); +#endif /* !JERRY_BUILTIN_REALMS */ /* 1. */ switch (CBC_FUNCTION_GET_TYPE (status_flags)) @@ -1143,1088 +1301,168 @@ ecma_op_function_call_simple (ecma_object_t *func_obj_p, /**< Function object */ #if JERRY_ESNEXT case CBC_FUNCTION_CONSTRUCTOR: { - return ecma_op_function_call_constructor (&shared_args, scope_p, this_binding); + return ecma_raise_type_error (ECMA_ERR_CLASS_CONSTRUCTOR_REQUIRES_NEW); } case CBC_FUNCTION_ARROW: { - ecma_arrow_function_t *arrow_func_p = (ecma_arrow_function_t *) func_obj_p; - - if (ecma_is_value_undefined (arrow_func_p->new_target)) - { - JERRY_CONTEXT (current_new_target_p) = NULL; - } - else - { - JERRY_CONTEXT (current_new_target_p) = ecma_get_object_from_value (arrow_func_p->new_target); - } - - this_binding = arrow_func_p->this_binding; - - if (JERRY_UNLIKELY (this_binding == ECMA_VALUE_UNINITIALIZED)) - { - ecma_environment_record_t *env_record_p = ecma_op_get_environment_record (scope_p); - JERRY_ASSERT (env_record_p); - this_binding = env_record_p->this_binding; - } + shared_args.header.status_flags &= (uint32_t) ~VM_FRAME_CTX_SHARED_NON_ARROW_FUNC; + this_value = ecma_arrow_function_object_bind_this (func_obj_p, scope_p); break; } - #endif /* JERRY_ESNEXT */ default: { -#if JERRY_ESNEXT - shared_args.header.status_flags |= VM_FRAME_CTX_SHARED_NON_ARROW_FUNC; -#endif /* JERRY_ESNEXT */ - - if (status_flags & CBC_CODE_FLAGS_STRICT_MODE) + if (!(status_flags & CBC_CODE_FLAGS_STRICT_MODE)) { - break; + this_value = ecma_function_object_bind_this (&shared_args, this_value, realm_p); } - if (ecma_is_value_undefined (this_binding) || ecma_is_value_null (this_binding)) - { - /* 2. */ -#if JERRY_BUILTIN_REALMS - this_binding = realm_p->this_binding; -#else /* !JERRY_BUILTIN_REALMS */ - this_binding = ecma_make_object_value (ecma_builtin_get_global ()); -#endif /* JERRY_BUILTIN_REALMS */ - } - else if (!ecma_is_value_object (this_binding)) - { - /* 3., 4. */ - this_binding = ecma_op_to_object (this_binding); - shared_args.header.status_flags |= VM_FRAME_CTX_SHARED_FREE_THIS; - - JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (this_binding)); - } +#if JERRY_ESNEXT + JERRY_CONTEXT (current_new_target_p) = NULL; +#endif /* JERRY_ESNEXT */ break; } } #if JERRY_BUILTIN_REALMS - ecma_global_object_t *saved_global_object_p = JERRY_CONTEXT (global_object_p); JERRY_CONTEXT (global_object_p) = realm_p; #endif /* JERRY_BUILTIN_REALMS */ - ecma_value_t ret_value = vm_run (&shared_args.header, this_binding, scope_p); - -#if JERRY_BUILTIN_REALMS - JERRY_CONTEXT (global_object_p) = saved_global_object_p; -#endif /* JERRY_BUILTIN_REALMS */ + ecma_value_t result; - if (JERRY_UNLIKELY (shared_args.header.status_flags & VM_FRAME_CTX_SHARED_FREE_LOCAL_ENV)) + if (!(status_flags & CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED)) { + scope_p = ecma_create_decl_lex_env (scope_p); + result = vm_run (&shared_args.header, this_value, scope_p); ecma_deref_object (scope_p); } + else + { + result = vm_run (&shared_args.header, this_value, scope_p); + } + +#if JERRY_BUILTIN_REALMS + JERRY_CONTEXT (global_object_p) = saved_global_object_p; +#endif /* JERRY_BUILTIN_REALMS */ +#if JERRY_ESNEXT + JERRY_CONTEXT (current_new_target_p) = old_new_target_p; +#endif /* JERRY_ESNEXT */ if (JERRY_UNLIKELY (shared_args.header.status_flags & VM_FRAME_CTX_SHARED_FREE_THIS)) { - ecma_free_value (this_binding); + ecma_free_value (this_value); } - return ret_value; -} /* ecma_op_function_call_simple */ + return result; +} /* ecma_function_object_call */ /** - * Perform a built-in method call. + * General [[Construct]] implementation for function objects + * + * See also: ECMAScript v6, 9.2.2 * - * @return the result of the function call. + * @return ecma value + * Returned value must be freed with ecma_free_value */ -static ecma_value_t JERRY_ATTR_NOINLINE -ecma_op_function_call_native_built_in (ecma_object_t *func_obj_p, /**< Function object */ - ecma_value_t this_arg_value, /**< 'this' argument's value */ - const ecma_value_t *arguments_list_p, /**< arguments list */ - uint32_t arguments_list_len) /**< length of arguments list */ +ecma_value_t +ecma_function_object_construct (ecma_object_t *func_obj_p, /**< Function object */ + ecma_object_t *new_target_p, /**< new target */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< length of arguments list */ { - JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION); + JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION); -#if JERRY_BUILTIN_REALMS - ecma_global_object_t *saved_global_object_p = JERRY_CONTEXT (global_object_p); + ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) func_obj_p; + ecma_object_t *scope_p = ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, ext_func_p->u.function.scope_cp); + const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p); - ecma_extended_object_t *ext_func_obj_p = (ecma_extended_object_t *) func_obj_p; - JERRY_CONTEXT (global_object_p) = - ECMA_GET_INTERNAL_VALUE_POINTER (ecma_global_object_t, ext_func_obj_p->u.built_in.realm_value); -#endif /* JERRY_BUILTIN_REALMS */ + uint16_t status_flags = bytecode_data_p->status_flags; - ecma_value_t ret_value = - ecma_builtin_dispatch_call (func_obj_p, this_arg_value, arguments_list_p, arguments_list_len); +#if JERRY_ESNEXT + if (CBC_FUNCTION_GET_TYPE (status_flags) == CBC_FUNCTION_CONSTRUCTOR) + { + return ecma_function_object_construct_constructor (func_obj_p, new_target_p, arguments_list_p, arguments_list_len); + } +#endif /* JERRY_ESNEXT */ -#if JERRY_BUILTIN_REALMS - JERRY_CONTEXT (global_object_p) = saved_global_object_p; -#endif /* JERRY_BUILTIN_REALMS */ - return ret_value; -} /* ecma_op_function_call_native_built_in */ - -/** - * Perform a native C method call which was registered via the API. - * - * @return the result of the function call. - */ -static ecma_value_t JERRY_ATTR_NOINLINE -ecma_op_function_call_native (ecma_object_t *func_obj_p, /**< Function object */ - ecma_value_t this_arg_value, /**< 'this' argument's value */ - const ecma_value_t *arguments_list_p, /**< arguments list */ - uint32_t arguments_list_len) /**< length of arguments list */ -{ - JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_NATIVE_FUNCTION); - - ecma_native_function_t *native_function_p = (ecma_native_function_t *) func_obj_p; - -#if JERRY_BUILTIN_REALMS - ecma_global_object_t *saved_global_object_p = JERRY_CONTEXT (global_object_p); - JERRY_CONTEXT (global_object_p) = - ECMA_GET_INTERNAL_VALUE_POINTER (ecma_global_object_t, native_function_p->realm_value); -#endif /* JERRY_BUILTIN_REALMS */ - - jerry_call_info_t call_info; - call_info.function = ecma_make_object_value (func_obj_p); - call_info.this_value = this_arg_value; - -#if JERRY_ESNEXT - ecma_object_t *new_target_p = JERRY_CONTEXT (current_new_target_p); - call_info.new_target = (new_target_p == NULL) ? ECMA_VALUE_UNDEFINED : ecma_make_object_value (new_target_p); -#else /* JERRY_ESNEXT */ - call_info.new_target = ECMA_VALUE_UNDEFINED; -#endif /* JERRY_ESNEXT */ - - JERRY_ASSERT (native_function_p->native_handler_cb != NULL); - ecma_value_t ret_value = native_function_p->native_handler_cb (&call_info, arguments_list_p, arguments_list_len); -#if JERRY_BUILTIN_REALMS - JERRY_CONTEXT (global_object_p) = saved_global_object_p; -#endif /* JERRY_BUILTIN_REALMS */ - - if (JERRY_UNLIKELY (ecma_is_value_exception (ret_value))) - { - ecma_throw_exception (ret_value); - return ECMA_VALUE_ERROR; - } - -#if JERRY_DEBUGGER - JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_VM_EXCEPTION_THROWN); -#endif /* JERRY_DEBUGGER */ - return ret_value; -} /* ecma_op_function_call_native */ - -/** - * Append the bound arguments into the given collection - * - * Note: - * - The whole bound chain is resolved - * - The first element of the collection contains the bounded this value - * - * @return target function of the bound function - */ -JERRY_ATTR_NOINLINE static ecma_object_t * -ecma_op_bound_function_get_argument_list (ecma_object_t *func_obj_p, /**< bound bunction object */ - ecma_collection_t *list_p) /**< list of arguments */ -{ - JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION); - - ecma_bound_function_t *bound_func_p = (ecma_bound_function_t *) func_obj_p; - - func_obj_p = - ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, bound_func_p->header.u.bound_function.target_function); - - ecma_value_t args_len_or_this = bound_func_p->header.u.bound_function.args_len_or_this; - - uint32_t args_length = 1; - - if (ecma_is_value_integer_number (args_len_or_this)) - { - args_length = (uint32_t) ecma_get_integer_from_value (args_len_or_this); - } - - /* 5. */ - if (args_length != 1) - { - const ecma_value_t *args_p = (const ecma_value_t *) (bound_func_p + 1); - list_p->buffer_p[0] = *args_p; - - if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION) - { - func_obj_p = ecma_op_bound_function_get_argument_list (func_obj_p, list_p); - } - ecma_collection_append (list_p, args_p + 1, args_length - 1); - } - else - { - list_p->buffer_p[0] = args_len_or_this; - } - - return func_obj_p; -} /* ecma_op_bound_function_get_argument_list */ - -/** - * [[Call]] internal method for bound function objects - * - * @return ecma value - * Returned value must be freed with ecma_free_value - */ -static ecma_value_t JERRY_ATTR_NOINLINE -ecma_op_function_call_bound (ecma_object_t *func_obj_p, /**< Function object */ - const ecma_value_t *arguments_list_p, /**< arguments list */ - uint32_t arguments_list_len) /**< length of arguments list */ -{ - JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION); - - JERRY_CONTEXT (status_flags) &= (uint32_t) ~ECMA_STATUS_DIRECT_EVAL; - - ecma_collection_t *bound_arg_list_p = ecma_new_collection (); - ecma_collection_push_back (bound_arg_list_p, ECMA_VALUE_EMPTY); - - ecma_object_t *target_obj_p = ecma_op_bound_function_get_argument_list (func_obj_p, bound_arg_list_p); - - ecma_collection_append (bound_arg_list_p, arguments_list_p, arguments_list_len); - - JERRY_ASSERT (!ecma_is_value_empty (bound_arg_list_p->buffer_p[0])); - - ecma_value_t ret_value = ecma_op_function_call (target_obj_p, - bound_arg_list_p->buffer_p[0], - bound_arg_list_p->buffer_p + 1, - (uint32_t) (bound_arg_list_p->item_count - 1)); - - ecma_collection_destroy (bound_arg_list_p); - - return ret_value; -} /* ecma_op_function_call_bound */ - -/** - * General [[Call]] implementation - * - * @return ecma value - * Returned value must be freed with ecma_free_value - */ -extern inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE -ecma_op_function_validated_call (ecma_value_t callee, /**< callee */ - ecma_value_t this_arg_value, /**< 'this' argument's value */ - const ecma_value_t *arguments_list_p, /**< arguments list */ - uint32_t arguments_list_len) /**< length of arguments list */ -{ - if (!ecma_is_value_object (callee)) - { - return ecma_raise_type_error (ECMA_ERR_EXPECTED_A_FUNCTION); - } - - return ecma_op_function_call (ecma_get_object_from_value (callee), - this_arg_value, - arguments_list_p, - arguments_list_len); -} /* ecma_op_function_validated_call */ - -/** - * General [[Call]] implementation - * - * @return ecma value - * Returned value must be freed with ecma_free_value - */ -ecma_value_t -ecma_op_function_call (ecma_object_t *func_obj_p, /**< Function object */ - ecma_value_t this_arg_value, /**< 'this' argument's value */ - const ecma_value_t *arguments_list_p, /**< arguments list */ - uint32_t arguments_list_len) /**< length of arguments list */ -{ - JERRY_ASSERT (func_obj_p != NULL && !ecma_is_lexical_environment (func_obj_p)); - - ECMA_CHECK_STACK_USAGE (); - -#if JERRY_ESNEXT - ecma_object_t *old_new_target_p = JERRY_CONTEXT (current_new_target_p); - - if (JERRY_UNLIKELY (!(JERRY_CONTEXT (status_flags) & ECMA_STATUS_DIRECT_EVAL))) - { - JERRY_CONTEXT (current_new_target_p) = NULL; - } -#endif /* JERRY_ESNEXT */ - - ecma_value_t result; - - switch (ecma_get_object_type (func_obj_p)) - { - case ECMA_OBJECT_TYPE_FUNCTION: - { - result = ecma_op_function_call_simple (func_obj_p, this_arg_value, arguments_list_p, arguments_list_len); - break; - } - case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION: - { - result = ecma_op_function_call_native_built_in (func_obj_p, this_arg_value, arguments_list_p, arguments_list_len); - break; - } -#if JERRY_BUILTIN_PROXY - case ECMA_OBJECT_TYPE_PROXY: - { - result = ecma_proxy_object_call (func_obj_p, this_arg_value, arguments_list_p, arguments_list_len); - break; - } -#endif /* JERRY_BUILTIN_PROXY */ -#if JERRY_ESNEXT - case ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION: - { - result = ecma_raise_type_error (ECMA_ERR_CLASS_CONSTRUCTOR_NEW); - break; - } -#endif /* JERRY_ESNEXT */ - case ECMA_OBJECT_TYPE_NATIVE_FUNCTION: - { - result = ecma_op_function_call_native (func_obj_p, this_arg_value, arguments_list_p, arguments_list_len); - break; - } - case ECMA_OBJECT_TYPE_BOUND_FUNCTION: - { - result = ecma_op_function_call_bound (func_obj_p, arguments_list_p, arguments_list_len); - break; - } - default: - { - result = ecma_raise_type_error (ECMA_ERR_EXPECTED_A_FUNCTION); - break; - } - } - -#if JERRY_ESNEXT - JERRY_CONTEXT (current_new_target_p) = old_new_target_p; -#endif /* JERRY_ESNEXT */ - - return result; -} /* ecma_op_function_call */ - -/** - * [[Construct]] internal method for ECMAScript function objects - * - * @return ecma value - * Returned value must be freed with ecma_free_value - */ -static ecma_value_t -ecma_op_function_construct_simple (ecma_object_t *func_obj_p, /**< Function object */ - ecma_object_t *new_target_p, /**< new target */ - const ecma_value_t *arguments_list_p, /**< arguments list */ - uint32_t arguments_list_len) /**< length of arguments list */ -{ - JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION); - - ecma_object_t *new_this_obj_p = NULL; - ecma_value_t this_arg; - -#if JERRY_ESNEXT - ecma_extended_object_t *ext_func_obj_p = (ecma_extended_object_t *) func_obj_p; - - /* 5. */ - if (!ECMA_GET_THIRD_BIT_FROM_POINTER_TAG (ext_func_obj_p->u.function.scope_cp)) - { -#endif /* JERRY_ESNEXT */ - /* 5.a */ - ecma_object_t *proto_p = ecma_op_get_prototype_from_constructor (new_target_p, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); - - /* 5.b */ - if (JERRY_UNLIKELY (proto_p == NULL)) - { - return ECMA_VALUE_ERROR; - } - - new_this_obj_p = ecma_create_object (proto_p, 0, ECMA_OBJECT_TYPE_GENERAL); - ecma_deref_object (proto_p); - this_arg = ecma_make_object_value (new_this_obj_p); -#if JERRY_ESNEXT - } - else - { - this_arg = ECMA_VALUE_UNDEFINED; - } - - /* 6. */ - ecma_object_t *old_new_target_p = JERRY_CONTEXT (current_new_target_p); - JERRY_CONTEXT (current_new_target_p) = new_target_p; -#endif /* JERRY_ESNEXT */ - - ecma_value_t ret_value = ecma_op_function_call_simple (func_obj_p, this_arg, arguments_list_p, arguments_list_len); - -#if JERRY_ESNEXT - JERRY_CONTEXT (current_new_target_p) = old_new_target_p; -#endif /* JERRY_ESNEXT */ - - /* 13.a */ - if (ECMA_IS_VALUE_ERROR (ret_value) || ecma_is_value_object (ret_value)) - { -#if JERRY_ESNEXT - if (new_this_obj_p != NULL) - { - ecma_deref_object (new_this_obj_p); - } -#else /* !JERRY_ESNEXT */ - ecma_deref_object (new_this_obj_p); -#endif /* JERRY_ESNEXT */ - return ret_value; - } - - /* 13.b */ - ecma_free_value (ret_value); - return this_arg; -} /* ecma_op_function_construct_simple */ - -/** - * [[Construct]] internal method for built-in function objects - * - * @return ecma value - * Returned value must be freed with ecma_free_value - */ -static ecma_value_t -ecma_op_function_construct_built_in (ecma_object_t *func_obj_p, /**< Function object */ - ecma_object_t *new_target_p, /**< new target */ - const ecma_value_t *arguments_list_p, /**< arguments list */ - uint32_t arguments_list_len) /**< length of arguments list */ -{ - JERRY_UNUSED (new_target_p); - - JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION); - -#if JERRY_BUILTIN_REALMS - ecma_global_object_t *saved_global_object_p = JERRY_CONTEXT (global_object_p); - ecma_value_t realm_value = ((ecma_extended_object_t *) func_obj_p)->u.built_in.realm_value; - JERRY_CONTEXT (global_object_p) = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_global_object_t, realm_value); -#endif /* JERRY_BUILTIN_REALMS */ - -#if JERRY_ESNEXT - ecma_object_t *old_new_target = JERRY_CONTEXT (current_new_target_p); - JERRY_CONTEXT (current_new_target_p) = new_target_p; -#endif /* JERRY_ESNEXT */ - - ecma_value_t ret_value = ecma_builtin_dispatch_construct (func_obj_p, arguments_list_p, arguments_list_len); - -#if JERRY_ESNEXT - JERRY_CONTEXT (current_new_target_p) = old_new_target; -#endif /* JERRY_ESNEXT */ - -#if JERRY_BUILTIN_REALMS - JERRY_CONTEXT (global_object_p) = saved_global_object_p; -#endif /* JERRY_BUILTIN_REALMS */ - return ret_value; -} /* ecma_op_function_construct_built_in */ - -/** - * [[Construct]] internal method for bound function objects - * - * @return ecma value - * Returned value must be freed with ecma_free_value - */ -static ecma_value_t JERRY_ATTR_NOINLINE -ecma_op_function_construct_bound (ecma_object_t *func_obj_p, /**< Function object */ - ecma_object_t *new_target_p, /**< new target */ - const ecma_value_t *arguments_list_p, /**< arguments list */ - uint32_t arguments_list_len) /**< length of arguments list */ -{ - JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION); - - ecma_collection_t *bound_arg_list_p = ecma_new_collection (); - ecma_collection_push_back (bound_arg_list_p, ECMA_VALUE_EMPTY); - - ecma_object_t *target_obj_p = ecma_op_bound_function_get_argument_list (func_obj_p, bound_arg_list_p); - - ecma_collection_append (bound_arg_list_p, arguments_list_p, arguments_list_len); - - if (func_obj_p == new_target_p) - { - new_target_p = target_obj_p; - } - - ecma_value_t ret_value = ecma_op_function_construct (target_obj_p, - new_target_p, - bound_arg_list_p->buffer_p + 1, - (uint32_t) (bound_arg_list_p->item_count - 1)); - - ecma_collection_destroy (bound_arg_list_p); - - return ret_value; -} /* ecma_op_function_construct_bound */ - -#if JERRY_ESNEXT - -/** - * [[Construct]] internal method for class implicit constructor objects - * - * @return ecma value - * Returned value must be freed with ecma_free_value - */ -static ecma_value_t -ecma_op_function_construct_constructor (ecma_object_t *func_obj_p, /**< Function object */ - ecma_object_t *new_target_p, /**< new target */ - const ecma_value_t *arguments_list_p, /**< arguments list */ - uint32_t arguments_list_len) /**< length of arguments list */ -{ - JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION); - - ecma_extended_object_t *constructor_object_p = (ecma_extended_object_t *) func_obj_p; - - if (!(constructor_object_p->u.constructor_function.flags & ECMA_CONSTRUCTOR_FUNCTION_HAS_HERITAGE)) - { - ecma_object_t *proto_p = ecma_op_get_prototype_from_constructor (new_target_p, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); - - if (JERRY_UNLIKELY (proto_p == NULL)) - { - return ECMA_VALUE_ERROR; - } - - ecma_object_t *new_this_object_p = ecma_create_object (proto_p, 0, ECMA_OBJECT_TYPE_GENERAL); - ecma_deref_object (proto_p); - - jerry_value_t new_this_value = ecma_make_object_value (new_this_object_p); - jerry_value_t ret_value = opfunc_init_class_fields (func_obj_p, new_this_value); - - if (ECMA_IS_VALUE_ERROR (ret_value)) - { - ecma_deref_object (new_this_object_p); - return ret_value; - } - - return new_this_value; - } - - ecma_value_t super_ctor = ecma_op_function_get_super_constructor (func_obj_p); - - if (ECMA_IS_VALUE_ERROR (super_ctor)) - { - return super_ctor; - } - - ecma_object_t *super_ctor_p = ecma_get_object_from_value (super_ctor); - ecma_value_t result = ecma_op_function_construct (super_ctor_p, new_target_p, arguments_list_p, arguments_list_len); - ecma_deref_object (super_ctor_p); - - if (ecma_is_value_object (result)) - { - ecma_value_t fields_value = opfunc_init_class_fields (func_obj_p, result); - - if (ECMA_IS_VALUE_ERROR (fields_value)) - { - ecma_free_value (result); - return fields_value; - } - } - - return result; -} /* ecma_op_function_construct_constructor */ - -#endif /* JERRY_ESNEXT */ - -/** - * [[Construct]] internal method for external function objects - * - * @return ecma value - * Returned value must be freed with ecma_free_value - */ -static ecma_value_t -ecma_op_function_construct_native (ecma_object_t *func_obj_p, /**< Function object */ - ecma_object_t *new_target_p, /**< new target */ - const ecma_value_t *arguments_list_p, /**< arguments list */ - uint32_t arguments_list_len) /**< length of arguments list */ -{ - JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_NATIVE_FUNCTION); - - ecma_object_t *proto_p = ecma_op_get_prototype_from_constructor (new_target_p, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); - - if (JERRY_UNLIKELY (proto_p == NULL)) - { - return ECMA_VALUE_ERROR; - } - - ecma_object_t *new_this_obj_p = ecma_create_object (proto_p, 0, ECMA_OBJECT_TYPE_GENERAL); - ecma_value_t this_arg = ecma_make_object_value (new_this_obj_p); - ecma_deref_object (proto_p); - -#if JERRY_ESNEXT - ecma_object_t *old_new_target_p = JERRY_CONTEXT (current_new_target_p); - JERRY_CONTEXT (current_new_target_p) = new_target_p; -#endif /* JERRY_ESNEXT */ - - ecma_value_t ret_value = ecma_op_function_call_native (func_obj_p, this_arg, arguments_list_p, arguments_list_len); - -#if JERRY_ESNEXT - JERRY_CONTEXT (current_new_target_p) = old_new_target_p; -#endif /* JERRY_ESNEXT */ - - if (ECMA_IS_VALUE_ERROR (ret_value) || ecma_is_value_object (ret_value)) - { - ecma_deref_object (new_this_obj_p); - return ret_value; - } - - ecma_free_value (ret_value); - - return this_arg; -} /* ecma_op_function_construct_native */ - -/** - * General [[Construct]] implementation function objects - * - * See also: ECMAScript v6, 9.2.2 - * - * @return ecma value - * Returned value must be freed with ecma_free_value - */ -ecma_value_t -ecma_op_function_construct (ecma_object_t *func_obj_p, /**< Function object */ - ecma_object_t *new_target_p, /**< new target */ - const ecma_value_t *arguments_list_p, /**< arguments list */ - uint32_t arguments_list_len) /**< length of arguments list */ -{ - JERRY_ASSERT (func_obj_p != NULL && !ecma_is_lexical_environment (func_obj_p)); - - ECMA_CHECK_STACK_USAGE (); - - switch (ecma_get_object_type (func_obj_p)) - { - case ECMA_OBJECT_TYPE_FUNCTION: - { - return ecma_op_function_construct_simple (func_obj_p, new_target_p, arguments_list_p, arguments_list_len); - } - case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION: - { - return ecma_op_function_construct_built_in (func_obj_p, new_target_p, arguments_list_p, arguments_list_len); - } -#if JERRY_BUILTIN_PROXY - case ECMA_OBJECT_TYPE_PROXY: - { - return ecma_proxy_object_construct (func_obj_p, new_target_p, arguments_list_p, arguments_list_len); - } -#endif /* JERRY_BUILTIN_PROXY */ -#if JERRY_ESNEXT - case ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION: - { - return ecma_op_function_construct_constructor (func_obj_p, new_target_p, arguments_list_p, arguments_list_len); - } -#endif /* JERRY_ESNEXT */ - case ECMA_OBJECT_TYPE_BOUND_FUNCTION: - { - return ecma_op_function_construct_bound (func_obj_p, new_target_p, arguments_list_p, arguments_list_len); - } - case ECMA_OBJECT_TYPE_NATIVE_FUNCTION: - { - return ecma_op_function_construct_native (func_obj_p, new_target_p, arguments_list_p, arguments_list_len); - } - default: - { - JERRY_UNREACHABLE (); - } - } - - return ECMA_VALUE_UNDEFINED; -} /* ecma_op_function_construct */ - -/** - * Lazy instantiation of 'prototype' property for non-builtin and external functions - * - * @return pointer to newly instantiated property - */ -static ecma_property_t * -ecma_op_lazy_instantiate_prototype_object (ecma_object_t *object_p) /**< the function object */ -{ - JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_FUNCTION - || ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_NATIVE_FUNCTION); - -#if JERRY_BUILTIN_REALMS - ecma_global_object_t *global_object_p; - - if (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_FUNCTION) - { - const ecma_compiled_code_t *bytecode_data_p; - bytecode_data_p = ecma_op_function_get_compiled_code ((ecma_extended_object_t *) object_p); - - global_object_p = ecma_op_function_get_realm (bytecode_data_p); - } - else - { - ecma_native_function_t *native_function_p = (ecma_native_function_t *) object_p; - - global_object_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_global_object_t, native_function_p->realm_value); - } -#endif /* JERRY_BUILTIN_REALMS */ - - /* ECMA-262 v5, 13.2, 16-18 */ - - ecma_object_t *proto_object_p = NULL; - bool init_constructor = true; - -#if JERRY_ESNEXT - if (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_FUNCTION) - { - const ecma_compiled_code_t *byte_code_p = ecma_op_function_get_compiled_code ((ecma_extended_object_t *) object_p); - - if (!CBC_FUNCTION_HAS_PROTOTYPE (byte_code_p->status_flags)) - { - return NULL; - } - - if (CBC_FUNCTION_GET_TYPE (byte_code_p->status_flags) == CBC_FUNCTION_GENERATOR) - { - ecma_object_t *prototype_p; - -#if JERRY_BUILTIN_REALMS - prototype_p = ecma_builtin_get_from_realm (global_object_p, ECMA_BUILTIN_ID_GENERATOR_PROTOTYPE); -#else /* !JERRY_BUILTIN_REALMS */ - prototype_p = ecma_builtin_get (ECMA_BUILTIN_ID_GENERATOR_PROTOTYPE); -#endif /* JERRY_BUILTIN_REALMS */ - - proto_object_p = ecma_create_object (prototype_p, 0, ECMA_OBJECT_TYPE_GENERAL); - init_constructor = false; - } - - if (CBC_FUNCTION_GET_TYPE (byte_code_p->status_flags) == CBC_FUNCTION_ASYNC_GENERATOR) - { - ecma_object_t *prototype_p; - -#if JERRY_BUILTIN_REALMS - prototype_p = ecma_builtin_get_from_realm (global_object_p, ECMA_BUILTIN_ID_ASYNC_GENERATOR_PROTOTYPE); -#else /* !JERRY_BUILTIN_REALMS */ - prototype_p = ecma_builtin_get (ECMA_BUILTIN_ID_ASYNC_GENERATOR_PROTOTYPE); -#endif /* JERRY_BUILTIN_REALMS */ - - proto_object_p = ecma_create_object (prototype_p, 0, ECMA_OBJECT_TYPE_GENERAL); - init_constructor = false; - } - } -#endif /* JERRY_ESNEXT */ - -#if JERRY_ESNEXT - if (proto_object_p == NULL) -#endif /* JERRY_ESNEXT */ - { - ecma_object_t *prototype_p; - -#if JERRY_BUILTIN_REALMS - prototype_p = ecma_builtin_get_from_realm (global_object_p, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); -#else /* !JERRY_BUILTIN_REALMS */ - prototype_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); -#endif /* JERRY_BUILTIN_REALMS */ + JERRY_ASSERT (CBC_FUNCTION_GET_TYPE (status_flags) == CBC_FUNCTION_NORMAL); - proto_object_p = ecma_op_create_object_object_noarg_and_set_prototype (prototype_p); - } + /* 5.a */ + ecma_object_t *proto_p = ecma_op_get_prototype_from_constructor (new_target_p, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); - /* 17. */ - if (init_constructor) + /* 5.b */ + if (JERRY_UNLIKELY (proto_p == NULL)) { - ecma_property_value_t *constructor_prop_value_p; - constructor_prop_value_p = ecma_create_named_data_property (proto_object_p, - ecma_get_magic_string (LIT_MAGIC_STRING_CONSTRUCTOR), - ECMA_PROPERTY_CONFIGURABLE_WRITABLE, - NULL); - - constructor_prop_value_p->value = ecma_make_object_value (object_p); + return ECMA_VALUE_ERROR; } - /* 18. */ - ecma_property_t *prototype_prop_p; - ecma_property_value_t *prototype_prop_value_p; - prototype_prop_value_p = ecma_create_named_data_property (object_p, - ecma_get_magic_string (LIT_MAGIC_STRING_PROTOTYPE), - ECMA_PROPERTY_BUILT_IN_WRITABLE, - &prototype_prop_p); - - prototype_prop_value_p->value = ecma_make_object_value (proto_object_p); - - ecma_deref_object (proto_object_p); - - return prototype_prop_p; -} /* ecma_op_lazy_instantiate_prototype_object */ - -/** - * Lazy instantiation of non-builtin ecma function object's properties - * - * Warning: - * Only non-configurable properties could be instantiated lazily in this function, - * as configurable properties could be deleted and it would be incorrect - * to reinstantiate them in the function in second time. - * - * @return pointer to newly instantiated property, if a property was instantiated, - * NULL - otherwise - */ -ecma_property_t * -ecma_op_function_try_to_lazy_instantiate_property (ecma_object_t *object_p, /**< the function object */ - ecma_string_t *property_name_p) /**< property name */ -{ - JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_FUNCTION); + ecma_object_t *new_this_obj_p = ecma_create_object (proto_p, 0, ECMA_OBJECT_TYPE_GENERAL); + ecma_deref_object (proto_p); + ecma_value_t this_value = ecma_make_object_value (new_this_obj_p); #if JERRY_ESNEXT - if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_LENGTH)) - { - ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p; - - if (ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (ext_func_p->u.function.scope_cp)) - { - return NULL; - } - - /* Initialize 'length' property */ - 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; - } - - if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_HAS_EXTENDED_INFO) - { - uint8_t *extended_info_p = ecma_compiled_code_resolve_extended_info (bytecode_data_p); - - if (*extended_info_p & CBC_EXTENDED_CODE_FLAGS_HAS_ARGUMENT_LENGTH) - { - len = ecma_extended_info_decode_vlq (&extended_info_p); - } - } - - ecma_property_t *value_prop_p; - ecma_property_value_t *value_p = - ecma_create_named_data_property (object_p, property_name_p, ECMA_PROPERTY_BUILT_IN_CONFIGURABLE, &value_prop_p); - value_p->value = ecma_make_uint32_value (len); - return value_prop_p; - } - - if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_NAME)) - { - ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p; - - if (ECMA_GET_SECOND_BIT_FROM_POINTER_TAG (ext_func_p->u.function.scope_cp)) - { - return NULL; - } - - const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p); - - if (CBC_FUNCTION_GET_TYPE (bytecode_data_p->status_flags) == CBC_FUNCTION_CONSTRUCTOR) - { - return NULL; - } - - ecma_value_t value = *ecma_compiled_code_resolve_function_name (bytecode_data_p); - JERRY_ASSERT (ecma_is_value_string (value)); - - /* Initialize 'name' property */ - ecma_property_t *value_prop_p; - ecma_property_value_t *value_p = - ecma_create_named_data_property (object_p, property_name_p, ECMA_PROPERTY_BUILT_IN_CONFIGURABLE, &value_prop_p); - value_p->value = ecma_copy_value (value); - return value_prop_p; - } + ecma_object_t *old_new_target_p = JERRY_CONTEXT (current_new_target_p); + JERRY_CONTEXT (current_new_target_p) = new_target_p; #endif /* JERRY_ESNEXT */ - if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_PROTOTYPE) - && ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_FUNCTION) - { - return ecma_op_lazy_instantiate_prototype_object (object_p); - } - - const bool is_arguments = ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_ARGUMENTS); - - if (is_arguments || ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_CALLER)) - { - const ecma_compiled_code_t *bytecode_data_p; - bytecode_data_p = ecma_op_function_get_compiled_code ((ecma_extended_object_t *) object_p); +#if JERRY_BUILTIN_REALMS + ecma_global_object_t *realm_p = ecma_op_function_get_realm (bytecode_data_p); + ecma_global_object_t *saved_global_object_p = JERRY_CONTEXT (global_object_p); + JERRY_CONTEXT (global_object_p) = realm_p; +#endif /* !JERRY_BUILTIN_REALMS */ + vm_frame_ctx_shared_args_t shared_args; #if JERRY_ESNEXT - if (!(bytecode_data_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) - && CBC_FUNCTION_GET_TYPE (bytecode_data_p->status_flags) == CBC_FUNCTION_NORMAL) - { - ecma_property_t *value_prop_p; - /* The property_name_p argument contains the name. */ - ecma_property_value_t *value_p = - ecma_create_named_data_property (object_p, property_name_p, ECMA_PROPERTY_BUILT_IN_FIXED, &value_prop_p); - value_p->value = is_arguments ? ECMA_VALUE_NULL : ECMA_VALUE_UNDEFINED; - return value_prop_p; - } + shared_args.header.status_flags = VM_FRAME_CTX_SHARED_HAS_ARG_LIST | VM_FRAME_CTX_SHARED_NON_ARROW_FUNC; #else /* !JERRY_ESNEXT */ - if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) - { - ecma_object_t *thrower_p = ecma_builtin_get (ECMA_BUILTIN_ID_TYPE_ERROR_THROWER); - - ecma_property_t *caller_prop_p; - /* The property_name_p argument contains the name. */ - ecma_create_named_accessor_property (object_p, - property_name_p, - thrower_p, - thrower_p, - ECMA_PROPERTY_BUILT_IN_FIXED, - &caller_prop_p); - return caller_prop_p; - } + shared_args.header.status_flags = VM_FRAME_CTX_SHARED_HAS_ARG_LIST; #endif /* JERRY_ESNEXT */ - } - - return NULL; -} /* ecma_op_function_try_to_lazy_instantiate_property */ - -/** - * Create specification defined non-configurable properties for external functions. - * - * See also: - * ECMA-262 v5, 15.3.4.5 - * - * @return pointer property, if one was instantiated, - * NULL - otherwise. - */ -ecma_property_t * -ecma_op_external_function_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_NATIVE_FUNCTION); - - if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_PROTOTYPE)) - { - return ecma_op_lazy_instantiate_prototype_object (object_p); - } - - return NULL; -} /* ecma_op_external_function_try_to_lazy_instantiate_property */ + shared_args.header.function_object_p = func_obj_p; + shared_args.arg_list_p = arguments_list_p; + shared_args.arg_list_len = arguments_list_len; + shared_args.header.bytecode_header_p = bytecode_data_p; -/** - * Create specification defined non-configurable properties for bound functions. - * - * See also: - * ECMA-262 v5, 15.3.4.5 - * - * @return pointer property, if one was instantiated, - * NULL - otherwise. - */ -ecma_property_t * -ecma_op_bound_function_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_BOUND_FUNCTION); + ecma_value_t result; - if (ecma_string_is_length (property_name_p)) + if (!(status_flags & CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED)) { - ecma_bound_function_t *bound_func_p = (ecma_bound_function_t *) object_p; - ecma_value_t args_len_or_this = bound_func_p->header.u.bound_function.args_len_or_this; - ecma_number_t length = 0; - ecma_integer_value_t args_length = 1; - uint8_t length_attributes; - - if (ecma_is_value_integer_number (args_len_or_this)) - { - args_length = ecma_get_integer_from_value (args_len_or_this); - } - -#if JERRY_ESNEXT - if (ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (bound_func_p->header.u.bound_function.target_function)) - { - return NULL; - } - - length_attributes = ECMA_PROPERTY_BUILT_IN_CONFIGURABLE; - length = ecma_get_number_from_value (bound_func_p->target_length) - (args_length - 1); -#else /* !JERRY_ESNEXT */ - length_attributes = ECMA_PROPERTY_BUILT_IN_FIXED; - - ecma_object_t *target_func_p; - target_func_p = - ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t, bound_func_p->header.u.bound_function.target_function); - - if (ecma_object_get_class_name (target_func_p) == LIT_MAGIC_STRING_FUNCTION_UL) - { - /* The property_name_p argument contains the 'length' string. */ - ecma_value_t get_len_value = ecma_op_object_get (target_func_p, property_name_p); - - JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (get_len_value)); - JERRY_ASSERT (ecma_is_value_integer_number (get_len_value)); - - length = (ecma_number_t) (ecma_get_integer_from_value (get_len_value) - (args_length - 1)); - } -#endif /* JERRY_ESNEXT */ - - if (length < 0) - { - length = 0; - } - - ecma_property_t *len_prop_p; - ecma_property_value_t *len_prop_value_p = - ecma_create_named_data_property (object_p, property_name_p, length_attributes, &len_prop_p); - - len_prop_value_p->value = ecma_make_number_value (length); - return len_prop_p; + scope_p = ecma_create_decl_lex_env (scope_p); + result = vm_run (&shared_args.header, this_value, scope_p); + ecma_deref_object (scope_p); } - -#if !JERRY_ESNEXT - if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_CALLER) - || ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_ARGUMENTS)) + else { - ecma_object_t *thrower_p = ecma_builtin_get (ECMA_BUILTIN_ID_TYPE_ERROR_THROWER); - - ecma_property_t *caller_prop_p; - /* The string_p argument contans the name. */ - ecma_create_named_accessor_property (object_p, - property_name_p, - thrower_p, - thrower_p, - ECMA_PROPERTY_BUILT_IN_FIXED, - &caller_prop_p); - return caller_prop_p; + result = vm_run (&shared_args.header, this_value, scope_p); } -#endif /* !JERRY_ESNEXT */ - - return NULL; -} /* ecma_op_bound_function_try_to_lazy_instantiate_property */ +#if JERRY_BUILTIN_REALMS + JERRY_CONTEXT (global_object_p) = saved_global_object_p; +#endif /* JERRY_BUILTIN_REALMS */ #if JERRY_ESNEXT + JERRY_CONTEXT (current_new_target_p) = old_new_target_p; +#endif /* JERRY_ESNEXT */ -/** - * Delete configurable properties of functions. - */ -void -ecma_op_function_delete_built_in_property (ecma_object_t *object_p, /**< object */ - ecma_string_t *property_name_p) /**< property name */ -{ - ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p; - - if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_LENGTH)) + /* 13.a */ + if (ECMA_IS_VALUE_ERROR (result) || ecma_is_value_object (result)) { - JERRY_ASSERT (!ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (ext_func_p->u.function.scope_cp)); - ECMA_SET_FIRST_BIT_TO_POINTER_TAG (ext_func_p->u.function.scope_cp); - return; + ecma_deref_object (new_this_obj_p); + return result; } - JERRY_ASSERT (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_NAME)); - JERRY_ASSERT (!ECMA_GET_SECOND_BIT_FROM_POINTER_TAG (ext_func_p->u.function.scope_cp)); - - ECMA_SET_SECOND_BIT_TO_POINTER_TAG (ext_func_p->u.function.scope_cp); -} /* ecma_op_function_delete_built_in_property */ - -/** - * Delete configurable properties of bound functions. - */ -void -ecma_op_bound_function_delete_built_in_property (ecma_object_t *object_p, /**< object */ - ecma_string_t *property_name_p) /**< property name */ -{ - JERRY_UNUSED (property_name_p); - - ecma_bound_function_t *bound_func_p = (ecma_bound_function_t *) object_p; - - JERRY_ASSERT (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_LENGTH)); - JERRY_ASSERT (!ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (bound_func_p->header.u.bound_function.target_function)); - - ECMA_SET_FIRST_BIT_TO_POINTER_TAG (bound_func_p->header.u.bound_function.target_function); -} /* ecma_op_bound_function_delete_built_in_property */ - -#endif /* JERRY_ESNEXT */ + /* 13.b */ + ecma_free_value (result); + return this_value; +} /* ecma_function_object_construct */ /** * List names of a Function object's lazy instantiated properties, * adding them to corresponding string collections - * - * See also: - * ecma_op_function_try_to_lazy_instantiate_property */ void -ecma_op_function_list_lazy_property_names (ecma_object_t *object_p, /**< functionobject */ - ecma_collection_t *prop_names_p, /**< prop name collection */ - ecma_property_counter_t *prop_counter_p, /**< property counters */ - jerry_property_filter_t filter) /**< property name filter options */ +ecma_function_object_list_lazy_property_keys (ecma_object_t *object_p, /**< functionobject */ + ecma_collection_t *prop_names_p, /**< prop name collection */ + ecma_property_counter_t *prop_counter_p, /**< property counters */ + jerry_property_filter_t filter) /**< property name filter options */ { if (filter & JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS) { @@ -2283,75 +1521,29 @@ ecma_op_function_list_lazy_property_names (ecma_object_t *object_p, /**< functio /* 'prototype' property is non-enumerable (ECMA-262 v5, 13.2.18) */ ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_PROTOTYPE)); prop_counter_p->string_named_props++; -} /* ecma_op_function_list_lazy_property_names */ +} /* ecma_function_object_list_lazy_property_keys */ /** - * List names of an External Function object's lazy instantiated properties, - * adding them to corresponding string collections - * - * See also: - * ecma_op_external_function_try_to_lazy_instantiate_property + * Delete configurable properties of functions. */ void -ecma_op_external_function_list_lazy_property_names (ecma_object_t *object_p, /**< function object */ - ecma_collection_t *prop_names_p, /**< prop name collection */ - ecma_property_counter_t *prop_counter_p, /**< property counters */ - jerry_property_filter_t filter) /**< property name - * filter options */ +ecma_function_object_delete_lazy_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *property_name_p) /**< property name */ { - JERRY_UNUSED (object_p); - - if (filter & JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS) - { - return; - } - - /* 'prototype' property is non-enumerable (ECMA-262 v5, 13.2.18) */ - ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_PROTOTYPE)); - prop_counter_p->string_named_props++; -} /* ecma_op_external_function_list_lazy_property_names */ + ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p; -/** - * List names of a Bound Function object's lazy instantiated properties, - * adding them to corresponding string collections - * - * See also: - * ecma_op_bound_function_try_to_lazy_instantiate_property - */ -void -ecma_op_bound_function_list_lazy_property_names (ecma_object_t *object_p, /**< bound function object*/ - ecma_collection_t *prop_names_p, /**< prop name collection */ - ecma_property_counter_t *prop_counter_p, /**< property counters */ - jerry_property_filter_t filter) /**< property name filter options */ -{ - if (filter & JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS) + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_LENGTH)) { + JERRY_ASSERT (!ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (ext_func_p->u.function.scope_cp)); + ECMA_SET_FIRST_BIT_TO_POINTER_TAG (ext_func_p->u.function.scope_cp); return; } -#if JERRY_ESNEXT - /* Unintialized 'length' property is non-enumerable (ECMA-262 v6, 19.2.4.1) */ - ecma_bound_function_t *bound_func_p = (ecma_bound_function_t *) object_p; - if (!ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (bound_func_p->header.u.bound_function.target_function)) - { - ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); - prop_counter_p->string_named_props++; - } -#else /* !JERRY_ESNEXT */ - JERRY_UNUSED (object_p); - /* 'length' property is non-enumerable (ECMA-262 v5, 13.2.5) */ - ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); - prop_counter_p->string_named_props++; -#endif /* JERRY_ESNEXT */ - - /* 'caller' property is non-enumerable (ECMA-262 v5, 13.2.5) */ - ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_CALLER)); - - /* 'arguments' property is non-enumerable (ECMA-262 v5, 13.2.5) */ - ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_ARGUMENTS)); + JERRY_ASSERT (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_NAME)); + JERRY_ASSERT (!ECMA_GET_SECOND_BIT_FROM_POINTER_TAG (ext_func_p->u.function.scope_cp)); - prop_counter_p->string_named_props += 2; -} /* ecma_op_bound_function_list_lazy_property_names */ + ECMA_SET_SECOND_BIT_TO_POINTER_TAG (ext_func_p->u.function.scope_cp); +} /* ecma_function_object_delete_lazy_property */ /** * @} diff --git a/jerry-core/ecma/operations/ecma-function-object.h b/jerry-core/ecma/operations/ecma-function-object.h index 3f9c602d2b..238359c9e5 100644 --- a/jerry-core/ecma/operations/ecma-function-object.h +++ b/jerry-core/ecma/operations/ecma-function-object.h @@ -76,58 +76,46 @@ ecma_object_t *ecma_op_create_arrow_function_object (ecma_object_t *scope_p, const ecma_compiled_code_t *bytecode_data_p, ecma_value_t this_binding); -ecma_object_t *ecma_op_create_native_handler (ecma_native_handler_id_t id, size_t object_size); - #endif /* JERRY_ESNEXT */ ecma_object_t *ecma_op_get_prototype_from_constructor (ecma_object_t *ctor_obj_p, ecma_builtin_id_t default_proto_id); ecma_value_t ecma_op_function_has_instance (ecma_object_t *func_obj_p, ecma_value_t value); -ecma_value_t ecma_op_function_validated_call (ecma_value_t callee, - ecma_value_t this_arg_value, - const ecma_value_t *arguments_list_p, - uint32_t arguments_list_len); - -ecma_value_t ecma_op_function_call (ecma_object_t *func_obj_p, - ecma_value_t this_arg_value, - const ecma_value_t *arguments_list_p, - uint32_t arguments_list_len); - -ecma_value_t ecma_op_function_construct (ecma_object_t *func_obj_p, - ecma_object_t *new_target_p, - const ecma_value_t *arguments_list_p, - uint32_t arguments_list_len); - -ecma_property_t *ecma_op_function_try_to_lazy_instantiate_property (ecma_object_t *object_p, - ecma_string_t *property_name_p); - -ecma_property_t *ecma_op_external_function_try_to_lazy_instantiate_property (ecma_object_t *object_p, - ecma_string_t *property_name_p); - -ecma_property_t *ecma_op_bound_function_try_to_lazy_instantiate_property (ecma_object_t *object_p, - ecma_string_t *property_name_p); - -#if JERRY_ESNEXT -void ecma_op_function_delete_built_in_property (ecma_object_t *object_p, ecma_string_t *property_name_p); - -void ecma_op_bound_function_delete_built_in_property (ecma_object_t *object_p, ecma_string_t *property_name_p); -#endif /* JERRY_ESNEXT */ - -void ecma_op_function_list_lazy_property_names (ecma_object_t *object_p, - ecma_collection_t *prop_names_p, - ecma_property_counter_t *prop_counter_p, - jerry_property_filter_t filter); +ecma_property_descriptor_t ecma_function_object_get_own_property (ecma_object_t *obj_p, ecma_string_t *property_name_p); +ecma_value_t ecma_function_object_call (ecma_object_t *func_obj_p, + ecma_value_t this_value, + const ecma_value_t *arguments_list_p, + uint32_t arguments_list_len); +ecma_value_t ecma_function_object_construct (ecma_object_t *func_obj_p, + ecma_object_t *new_target_p, + const ecma_value_t *arguments_list_p, + uint32_t arguments_list_len); +void ecma_function_object_list_lazy_property_keys (ecma_object_t *object_p, + ecma_collection_t *prop_names_p, + ecma_property_counter_t *prop_counter_p, + jerry_property_filter_t filter); +void ecma_function_object_delete_lazy_property (ecma_object_t *object_p, ecma_string_t *property_name_p); -void ecma_op_external_function_list_lazy_property_names (ecma_object_t *object_p, - ecma_collection_t *prop_names_p, - ecma_property_counter_t *prop_counter_p, - jerry_property_filter_t filter); - -void ecma_op_bound_function_list_lazy_property_names (ecma_object_t *object_p, - ecma_collection_t *prop_names_p, - ecma_property_counter_t *prop_counter_p, - jerry_property_filter_t filter); +/** + * Virtual function table for function object's internal methods + */ +#define ECMA_FUNCTION_OBJ_VTABLE \ + [ECMA_OBJECT_TYPE_FUNCTION] = { ecma_ordinary_object_get_prototype_of, \ + ecma_ordinary_object_set_prototype_of, \ + ecma_ordinary_object_is_extensible, \ + ecma_ordinary_object_prevent_extensions, \ + ecma_function_object_get_own_property, \ + ecma_ordinary_object_define_own_property, \ + ecma_ordinary_object_has_property, \ + ecma_ordinary_object_get, \ + ecma_ordinary_object_set, \ + ecma_ordinary_object_delete, \ + ecma_ordinary_object_own_property_keys, \ + ecma_function_object_call, \ + ecma_function_object_construct, \ + ecma_function_object_list_lazy_property_keys, \ + ecma_function_object_delete_lazy_property } /** * @} diff --git a/jerry-core/ecma/operations/ecma-get-put-value.c b/jerry-core/ecma/operations/ecma-get-put-value.c index 41bdf37d13..f22fbde9bc 100644 --- a/jerry-core/ecma/operations/ecma-get-put-value.c +++ b/jerry-core/ecma/operations/ecma-get-put-value.c @@ -211,7 +211,9 @@ ecma_op_get_value_object_base (ecma_value_t base_value, /**< base value */ obj_p = ecma_builtin_get (id); } - return ecma_op_object_get_with_receiver (obj_p, property_name_p, base_value); + ecma_value_t ret_value = ecma_internal_method_get (obj_p, property_name_p, base_value); + + return ret_value; } /* ecma_op_get_value_object_base */ /** @@ -279,7 +281,7 @@ ecma_op_put_value_lex_env_base (ecma_object_t *lex_env_p, /**< lexical environme ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); - ecma_value_t has_property = ecma_op_object_has_property (binding_obj_p, name_p); + ecma_value_t has_property = ecma_internal_method_has_property (binding_obj_p, name_p); #if JERRY_BUILTIN_PROXY if (ECMA_IS_VALUE_ERROR (has_property)) @@ -290,7 +292,8 @@ ecma_op_put_value_lex_env_base (ecma_object_t *lex_env_p, /**< lexical environme if (ecma_is_value_true (has_property)) { - ecma_value_t completion = ecma_op_object_put (binding_obj_p, name_p, value, is_strict); + ecma_value_t completion = + ecma_internal_method_set (binding_obj_p, name_p, value, ecma_make_object_value (binding_obj_p), is_strict); if (ECMA_IS_VALUE_ERROR (completion)) { @@ -326,7 +329,9 @@ ecma_op_put_value_lex_env_base (ecma_object_t *lex_env_p, /**< lexical environme #endif /* JERRY_ERROR_MESSAGES */ } - ecma_value_t completion = ecma_op_object_put (ecma_get_lex_env_binding_object (lex_env_p), name_p, value, false); + ecma_object_t *lex_env_binding_obj = ecma_get_lex_env_binding_object (lex_env_p); + ecma_value_t completion = + ecma_internal_method_set (lex_env_binding_obj, name_p, value, ecma_make_object_value (lex_env_binding_obj), false); JERRY_ASSERT (ecma_is_value_boolean (completion)); diff --git a/jerry-core/ecma/operations/ecma-iterator-object.c b/jerry-core/ecma/operations/ecma-iterator-object.c index 21d88724b1..968d6b9aad 100644 --- a/jerry-core/ecma/operations/ecma-iterator-object.c +++ b/jerry-core/ecma/operations/ecma-iterator-object.c @@ -241,7 +241,7 @@ ecma_op_get_iterator (ecma_value_t value, /**< value to get iterator from */ } /* 3. */ - ecma_value_t iterator = ecma_op_function_validated_call (method, value, NULL, 0); + ecma_value_t iterator = ecma_internal_method_validated_call (method, value, NULL, 0); if (use_default_method) { @@ -313,10 +313,10 @@ ecma_op_iterator_next (ecma_value_t iterator, /**< iterator value */ if (has_value) { - return ecma_op_function_call (next_method_obj_p, iterator, &value, 1); + return ecma_internal_method_call (next_method_obj_p, iterator, &value, 1); } - return ecma_op_function_call (next_method_obj_p, iterator, NULL, 0); + return ecma_internal_method_call (next_method_obj_p, iterator, NULL, 0); } /* ecma_op_iterator_next */ /** @@ -349,7 +349,7 @@ ecma_op_iterator_return (ecma_value_t iterator, /**< iterator value */ return ecma_create_iter_result_object (value, ECMA_VALUE_TRUE); } - ecma_value_t result = ecma_op_function_validated_call (func_return, iterator, &value, 1); + ecma_value_t result = ecma_internal_method_validated_call (func_return, iterator, &value, 1); ecma_free_value (func_return); return result; @@ -393,7 +393,7 @@ ecma_op_iterator_throw (ecma_value_t iterator, /**< iterator value */ return ecma_raise_type_error (ECMA_ERR_ITERATOR_THROW_IS_NOT_AVAILABLE); } - ecma_value_t result = ecma_op_function_validated_call (func_throw, iterator, &value, 1); + ecma_value_t result = ecma_internal_method_validated_call (func_throw, iterator, &value, 1); ecma_free_value (func_throw); return result; @@ -496,7 +496,7 @@ ecma_op_iterator_close (ecma_value_t iterator) /**< iterator value */ /* 6. */ ecma_object_t *return_obj_p = ecma_get_object_from_value (return_method); - ecma_value_t inner_result = ecma_op_function_call (return_obj_p, iterator, NULL, 0); + ecma_value_t inner_result = ecma_internal_method_call (return_obj_p, iterator, NULL, 0); ecma_deref_object (return_obj_p); /* 7. */ diff --git a/jerry-core/ecma/operations/ecma-jobqueue.c b/jerry-core/ecma/operations/ecma-jobqueue.c index 990e3b7a90..d9b28722b0 100644 --- a/jerry-core/ecma/operations/ecma-jobqueue.c +++ b/jerry-core/ecma/operations/ecma-jobqueue.c @@ -218,7 +218,7 @@ ecma_process_promise_reaction_job (ecma_job_promise_reaction_t *job_p) /**< the { /* 6. */ handler_result = - ecma_op_function_call (ecma_get_object_from_value (handler), ECMA_VALUE_UNDEFINED, &(job_p->argument), 1); + ecma_internal_method_call (ecma_get_object_from_value (handler), ECMA_VALUE_UNDEFINED, &(job_p->argument), 1); } ecma_value_t status; @@ -231,18 +231,18 @@ ecma_process_promise_reaction_job (ecma_job_promise_reaction_t *job_p) /**< the } /* 7. */ - status = ecma_op_function_call (ecma_get_object_from_value (capability_p->reject), - ECMA_VALUE_UNDEFINED, - &handler_result, - 1); + status = ecma_internal_method_call (ecma_get_object_from_value (capability_p->reject), + ECMA_VALUE_UNDEFINED, + &handler_result, + 1); } else { /* 8. */ - status = ecma_op_function_call (ecma_get_object_from_value (capability_p->resolve), - ECMA_VALUE_UNDEFINED, - &handler_result, - 1); + status = ecma_internal_method_call (ecma_get_object_from_value (capability_p->resolve), + ECMA_VALUE_UNDEFINED, + &handler_result, + 1); } ecma_free_value (handler_result); diff --git a/jerry-core/ecma/operations/ecma-lex-env.c b/jerry-core/ecma/operations/ecma-lex-env.c index ea1e8e297b..b765f4b3f4 100644 --- a/jerry-core/ecma/operations/ecma-lex-env.c +++ b/jerry-core/ecma/operations/ecma-lex-env.c @@ -186,7 +186,7 @@ ecma_op_has_binding (ecma_object_t *lex_env_p, /**< lexical environment */ ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); - return ecma_op_object_has_property (binding_obj_p, name_p); + return ecma_internal_method_has_property (binding_obj_p, name_p); } } } /* ecma_op_has_binding */ @@ -228,31 +228,19 @@ ecma_op_create_mutable_binding (ecma_object_t *lex_env_p, /**< lexical environme ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); -#if JERRY_BUILTIN_PROXY && JERRY_BUILTIN_REALMS - if (ECMA_OBJECT_IS_PROXY (binding_obj_p)) - { - ecma_value_t result = ecma_proxy_object_is_extensible (binding_obj_p); + ecma_value_t is_extensible = ecma_internal_method_is_extensible (binding_obj_p); - if (ECMA_IS_VALUE_ERROR (result)) - { - return ECMA_PROPERTY_POINTER_ERROR; - } - - if (result == ECMA_VALUE_FALSE) - { - return NULL; - } - } - else if (!ecma_op_ordinary_object_is_extensible (binding_obj_p)) +#if JERRY_BUILTIN_PROXY + if (ECMA_IS_VALUE_ERROR (is_extensible)) { - return NULL; + return ECMA_PROPERTY_POINTER_ERROR; } -#else /* !JERRY_BUILTIN_PROXY || !JERRY_BUILTIN_REALMS */ - if (!ecma_op_ordinary_object_is_extensible (binding_obj_p)) +#endif /* JERRY_BUILTIN_PROXY */ + + if (ecma_is_value_false (is_extensible)) { return NULL; } -#endif /* JERRY_BUILTIN_PROXY && JERRY_BUILTIN_REALMS */ const uint32_t flags = ECMA_PROPERTY_ENUMERABLE_WRITABLE | JERRY_PROP_SHOULD_THROW; @@ -335,7 +323,8 @@ ecma_op_set_mutable_binding (ecma_object_t *lex_env_p, /**< lexical environment ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); - ecma_value_t completion = ecma_op_object_put (binding_obj_p, name_p, value, is_strict); + ecma_value_t completion = + ecma_internal_method_set (binding_obj_p, name_p, value, ecma_make_object_value (binding_obj_p), is_strict); if (ECMA_IS_VALUE_ERROR (completion)) { @@ -376,7 +365,7 @@ ecma_op_get_binding_value (ecma_object_t *lex_env_p, /**< lexical environment */ ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); - ecma_value_t result = ecma_op_object_find (binding_obj_p, name_p); + ecma_value_t result = ecma_op_object_find (binding_obj_p, name_p, ecma_make_object_value (binding_obj_p)); if (ECMA_IS_VALUE_ERROR (result)) { @@ -448,7 +437,7 @@ ecma_op_delete_binding (ecma_object_t *lex_env_p, /**< lexical environment */ ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p); - return ecma_op_object_delete (binding_obj_p, name_p, false); + return ecma_internal_method_delete (binding_obj_p, name_p, false); } } /* ecma_op_delete_binding */ diff --git a/jerry-core/ecma/operations/ecma-native-function.c b/jerry-core/ecma/operations/ecma-native-function.c new file mode 100644 index 0000000000..0b017d63b3 --- /dev/null +++ b/jerry-core/ecma/operations/ecma-native-function.c @@ -0,0 +1,254 @@ +/* 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-native-function.h" + +#include "ecma-builtins.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-objects.h" +#include "ecma-ordinary-object.h" + +#include "jcontext.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmanativefunction ECMA native function related routines + * @{ + */ + +#if JERRY_ESNEXT + +/** + * Create built-in native handler object. + * + * @return pointer to newly created native handler object + */ +ecma_object_t * +ecma_native_function_create (ecma_native_handler_id_t id, /**< handler id */ + size_t object_size) /**< created object size */ +{ + ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE); + + ecma_object_t *function_obj_p = ecma_create_object (prototype_obj_p, object_size, ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION); + + ecma_extended_object_t *ext_func_obj_p = (ecma_extended_object_t *) function_obj_p; + ext_func_obj_p->u.built_in.id = ECMA_BUILTIN_ID_HANDLER; + ext_func_obj_p->u.built_in.routine_id = (uint8_t) id; + ext_func_obj_p->u.built_in.u2.routine_flags = ECMA_NATIVE_HANDLER_FLAGS_NONE; + +#if JERRY_BUILTIN_REALMS + ECMA_SET_INTERNAL_VALUE_POINTER (ext_func_obj_p->u.built_in.realm_value, ecma_builtin_get_global ()); +#endif /* JERRY_BUILTIN_REALMS */ + + return function_obj_p; +} /* ecma_native_function_create */ + +#endif /* JERRY_ESNEXT */ + +/** + * ecma native function object's [[GetOwnProperty]] internal method + * + * @return ecma property descriptor t + */ +ecma_property_descriptor_t +ecma_native_function_get_own_property (ecma_object_t *obj_p, /**< the object */ + ecma_string_t *property_name_p) /**< property name */ +{ + ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); + + prop_desc.u.property_p = ecma_find_named_property (obj_p, property_name_p); + + if (prop_desc.u.property_p != NULL) + { + prop_desc.flags = + ECMA_PROP_DESC_PROPERTY_FOUND | ECMA_PROPERTY_TO_PROPERTY_DESCRIPTOR_FLAGS (prop_desc.u.property_p); + return prop_desc; + } + + if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_PROTOTYPE)) + { +#if JERRY_BUILTIN_REALMS + ecma_global_object_t *global_object_p = + ECMA_GET_INTERNAL_VALUE_POINTER (ecma_global_object_t, ((ecma_native_function_t *) obj_p)->realm_value); + ecma_object_t *prototype_p = ecma_builtin_get_from_realm (global_object_p, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); +#else /* !JERRY_BUILTIN_REALMS */ + ecma_object_t *prototype_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); +#endif /* JERRY_BUILTIN_REALMS */ + + ecma_object_t *proto_object_p = ecma_create_object (prototype_p, 0, ECMA_OBJECT_TYPE_GENERAL); + + ecma_property_value_t *constructor_prop_value_p; + constructor_prop_value_p = ecma_create_named_data_property (proto_object_p, + ecma_get_magic_string (LIT_MAGIC_STRING_CONSTRUCTOR), + ECMA_PROPERTY_CONFIGURABLE_WRITABLE, + NULL); + + constructor_prop_value_p->value = ecma_make_object_value (obj_p); + + prop_desc.flags = ECMA_PROP_DESC_PROPERTY_FOUND | ECMA_PROP_DESC_DATA_WRITABLE; + ecma_property_value_t *prototype_prop_value_p; + prototype_prop_value_p = ecma_create_named_data_property (obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_PROTOTYPE), + ECMA_PROPERTY_BUILT_IN_WRITABLE, + &prop_desc.u.property_p); + + prototype_prop_value_p->value = ecma_make_object_value (proto_object_p); + + ecma_deref_object (proto_object_p); + return prop_desc; + } + + return prop_desc; +} /* ecma_native_function_get_own_property */ + +/** + * List lazy instantiated property names for native function object's + */ +void +ecma_native_object_list_lazy_property_keys (ecma_object_t *object_p, /**< function object */ + ecma_collection_t *prop_names_p, /**< prop name collection */ + ecma_property_counter_t *prop_counter_p, /**< property counters */ + jerry_property_filter_t filter) /**< property name + * filter options */ +{ + JERRY_UNUSED (object_p); + + if (filter & JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS) + { + return; + } + + /* 'prototype' property is non-enumerable (ECMA-262 v5, 13.2.18) */ + ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_PROTOTYPE)); + prop_counter_p->string_named_props++; +} /* ecma_native_object_list_lazy_property_keys */ + +/** + * Helper function to invoke native function with the prepaired jerry call info + * + * @return the result of the function call. + */ +static ecma_value_t +ecma_native_function_call_helper (ecma_object_t *func_obj_p, /**< Function object */ + jerry_call_info_t *call_info_p, /**< Function object */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< length of arguments list */ +{ + ecma_native_function_t *native_function_p = (ecma_native_function_t *) func_obj_p; + +#if JERRY_BUILTIN_REALMS + ecma_global_object_t *saved_global_object_p = JERRY_CONTEXT (global_object_p); + JERRY_CONTEXT (global_object_p) = + ECMA_GET_INTERNAL_VALUE_POINTER (ecma_global_object_t, native_function_p->realm_value); +#endif /* JERRY_BUILTIN_REALMS */ + + call_info_p->function = ecma_make_object_value (func_obj_p); + + JERRY_ASSERT (native_function_p->native_handler_cb != NULL); + ecma_value_t ret_value = native_function_p->native_handler_cb (call_info_p, arguments_list_p, arguments_list_len); +#if JERRY_BUILTIN_REALMS + JERRY_CONTEXT (global_object_p) = saved_global_object_p; +#endif /* JERRY_BUILTIN_REALMS */ + + if (JERRY_UNLIKELY (ecma_is_value_exception (ret_value))) + { + ecma_throw_exception (ret_value); + return ECMA_VALUE_ERROR; + } + +#if JERRY_DEBUGGER + JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_VM_EXCEPTION_THROWN); +#endif /* JERRY_DEBUGGER */ + return ret_value; +} /* ecma_native_function_call_helper */ + +/** + * Perform a native C method call which was registered via the API. + * + * @return the result of the function call. + */ +ecma_value_t +ecma_native_function_call (ecma_object_t *func_obj_p, /**< Function object */ + ecma_value_t this_arg_value, /**< 'this' argument's value */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< length of arguments list */ +{ + jerry_call_info_t call_info; + call_info.this_value = this_arg_value; + call_info.new_target = ECMA_VALUE_UNDEFINED; + + return ecma_native_function_call_helper (func_obj_p, &call_info, arguments_list_p, arguments_list_len); +} /* ecma_native_function_call */ + +/** + * ecma native function object's [[Construct]] internal method + * + * @return ecma value t + */ +ecma_value_t +ecma_native_function_construct (ecma_object_t *func_obj_p, /**< Function object */ + ecma_object_t *new_target_p, /**< new target */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< length of arguments list */ +{ + JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_NATIVE_FUNCTION); + + ecma_object_t *proto_p = ecma_op_get_prototype_from_constructor (new_target_p, ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); + + if (JERRY_UNLIKELY (proto_p == NULL)) + { + return ECMA_VALUE_ERROR; + } + + ecma_object_t *new_this_obj_p = ecma_create_object (proto_p, 0, ECMA_OBJECT_TYPE_GENERAL); + ecma_value_t this_arg = ecma_make_object_value (new_this_obj_p); + ecma_deref_object (proto_p); + + jerry_call_info_t call_info; + call_info.this_value = this_arg; + +#if JERRY_ESNEXT + ecma_object_t *old_new_target_p = JERRY_CONTEXT (current_new_target_p); + JERRY_CONTEXT (current_new_target_p) = new_target_p; + call_info.new_target = ecma_make_object_value (new_target_p); +#else /* JERRY_ESNEXT */ + call_info.new_target = ECMA_VALUE_UNDEFINED; +#endif /* JERRY_ESNEXT */ + + ecma_value_t ret_value = + ecma_native_function_call_helper (func_obj_p, &call_info, arguments_list_p, arguments_list_len); + +#if JERRY_ESNEXT + JERRY_CONTEXT (current_new_target_p) = old_new_target_p; +#endif /* JERRY_ESNEXT */ + + if (ECMA_IS_VALUE_ERROR (ret_value) || ecma_is_value_object (ret_value)) + { + ecma_deref_object (new_this_obj_p); + return ret_value; + } + + ecma_free_value (ret_value); + + return this_arg; +} /* ecma_native_function_construct */ + +/** + * @} + * @} + */ diff --git a/jerry-core/ecma/operations/ecma-native-function.h b/jerry-core/ecma/operations/ecma-native-function.h new file mode 100644 index 0000000000..114b41dd5e --- /dev/null +++ b/jerry-core/ecma/operations/ecma-native-function.h @@ -0,0 +1,72 @@ +/* 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. + */ + +#ifndef ECMA_OP_NATIVE_FUNCTION_H +#define ECMA_OP_NATIVE_FUNCTION_H + +#include "ecma-builtin-handlers.h" +#include "ecma-globals.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmanativefunction ECMA native function related routines + * @{ + */ + +#if JERRY_ESNEXT +ecma_object_t *ecma_native_function_create (ecma_native_handler_id_t id, size_t object_size); +#endif /* JERRY_ESNEXT */ + +ecma_property_descriptor_t ecma_native_function_get_own_property (ecma_object_t *obj_p, ecma_string_t *property_name_p); +void ecma_native_object_list_lazy_property_keys (ecma_object_t *object_p, + ecma_collection_t *prop_names_p, + ecma_property_counter_t *prop_counter_p, + jerry_property_filter_t filter); +ecma_value_t ecma_native_function_call (ecma_object_t *func_obj_p, + ecma_value_t this_arg_value, + const ecma_value_t *arguments_list_p, + uint32_t arguments_list_len); +ecma_value_t ecma_native_function_construct (ecma_object_t *func_obj_p, + ecma_object_t *new_target_p, + const ecma_value_t *arguments_list_p, + uint32_t arguments_list_len); + +/** + * Virtual function table for native function object's internal methods + */ +#define ECMA_NATIVE_FUNCTION_OBJ_VTABLE \ + [ECMA_OBJECT_TYPE_NATIVE_FUNCTION] = { ecma_ordinary_object_get_prototype_of, \ + ecma_ordinary_object_set_prototype_of, \ + ecma_ordinary_object_is_extensible, \ + ecma_ordinary_object_prevent_extensions, \ + ecma_native_function_get_own_property, \ + ecma_ordinary_object_define_own_property, \ + ecma_ordinary_object_has_property, \ + ecma_ordinary_object_get, \ + ecma_ordinary_object_set, \ + ecma_ordinary_object_delete, \ + ecma_ordinary_object_own_property_keys, \ + ecma_native_function_call, \ + ecma_native_function_construct, \ + ecma_native_object_list_lazy_property_keys, \ + ecma_ordinary_object_delete_lazy_property } + +/** + * @} + * @} + */ + +#endif /* !ECMA_OP_NATIVE_FUNCTION_H */ diff --git a/jerry-core/ecma/operations/ecma-objects-general.c b/jerry-core/ecma/operations/ecma-objects-general.c index a6c8f03633..82fee773cb 100644 --- a/jerry-core/ecma/operations/ecma-objects-general.c +++ b/jerry-core/ecma/operations/ecma-objects-general.c @@ -43,152 +43,9 @@ ecma_object_t * ecma_op_create_object_object_noarg (void) { - ecma_object_t *object_prototype_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE); - - /* 3., 4., 6., 7. */ - return ecma_op_create_object_object_noarg_and_set_prototype (object_prototype_p); + return ecma_create_object (ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE), 0, ECMA_OBJECT_TYPE_GENERAL); } /* ecma_op_create_object_object_noarg */ -/** - * Object creation operation with no arguments. - * It sets the given prototype to the newly created object. - * - * See also: ECMA-262 v5, 15.2.2.1, 15.2.3.5 - * - * @return pointer to newly created object - */ -ecma_object_t * -ecma_op_create_object_object_noarg_and_set_prototype (ecma_object_t *object_prototype_p) /**< pointer to prototype of - the object - (can be NULL) */ -{ - ecma_object_t *obj_p = ecma_create_object (object_prototype_p, 0, ECMA_OBJECT_TYPE_GENERAL); - - /* - * [[Class]] property of ECMA_OBJECT_TYPE_GENERAL type objects - * without ECMA_INTERNAL_PROPERTY_CLASS internal property - * is "Object". - * - * See also: ecma_object_get_class_name - */ - - return obj_p; -} /* ecma_op_create_object_object_noarg_and_set_prototype */ - -/** - * [[Delete]] ecma general object's operation - * - * See also: - * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 - * ECMA-262 v5, 8.12.7 - * - * @return ecma value - * Returned value must be freed with ecma_free_value - */ -ecma_value_t -ecma_op_general_object_delete (ecma_object_t *obj_p, /**< the object */ - ecma_string_t *property_name_p, /**< property name */ - bool is_throw) /**< flag that controls failure handling */ -{ - JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p)); - JERRY_ASSERT (property_name_p != NULL); - - /* 1. */ - ecma_property_ref_t property_ref; - - ecma_property_t property = - ecma_op_object_get_own_property (obj_p, property_name_p, &property_ref, ECMA_PROPERTY_GET_NO_OPTIONS); - - /* 2. */ - if (!ECMA_PROPERTY_IS_FOUND (property)) - { - JERRY_ASSERT (property == ECMA_PROPERTY_TYPE_NOT_FOUND || property == ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP); - return ECMA_VALUE_TRUE; - } - - /* 3. */ - if (!ecma_is_property_configurable (property)) - { - /* 4. */ - if (is_throw) - { - return ecma_raise_type_error (ECMA_ERR_EXPECTED_A_CONFIGURABLE_PROPERTY); - } - - /* 5. */ - return ECMA_VALUE_FALSE; - } - - ecma_object_type_t type = ecma_get_object_type (obj_p); - - if (type == ECMA_OBJECT_TYPE_ARRAY && ecma_array_object_delete_property (obj_p, property_name_p)) - { - return ECMA_VALUE_TRUE; - } - - /* a. */ - ecma_delete_property (obj_p, property_ref.value_p); - - if (property & ECMA_PROPERTY_FLAG_BUILT_IN) - { -#if JERRY_ESNEXT - switch (type) - { - case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION: - { - if (ecma_builtin_function_is_routine (obj_p)) - { - ecma_builtin_routine_delete_built_in_property (obj_p, property_name_p); - break; - } - /* FALLTHRU */ - } - case ECMA_OBJECT_TYPE_BUILT_IN_GENERAL: - case ECMA_OBJECT_TYPE_BUILT_IN_CLASS: - case ECMA_OBJECT_TYPE_BUILT_IN_ARRAY: - { - ecma_builtin_delete_built_in_property (obj_p, property_name_p); - break; - } - case ECMA_OBJECT_TYPE_CLASS: - { - JERRY_ASSERT (ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_ARGUMENTS)); - ecma_op_arguments_delete_built_in_property (obj_p, property_name_p); - break; - } - case ECMA_OBJECT_TYPE_FUNCTION: - { - ecma_op_function_delete_built_in_property (obj_p, property_name_p); - break; - } - case ECMA_OBJECT_TYPE_BOUND_FUNCTION: - { - ecma_op_bound_function_delete_built_in_property (obj_p, property_name_p); - break; - } - default: - { - JERRY_UNREACHABLE (); - break; - } - } -#else /* !JERRY_ESNEXT */ - if (type == ECMA_OBJECT_TYPE_CLASS) - { - JERRY_ASSERT (ecma_object_class_is (obj_p, ECMA_OBJECT_CLASS_ARGUMENTS)); - ecma_op_arguments_delete_built_in_property (obj_p, property_name_p); - } - else - { - ecma_builtin_delete_built_in_property (obj_p, property_name_p); - } -#endif /* JERRY_ESNEXT */ - } - - /* b. */ - return ECMA_VALUE_TRUE; -} /* ecma_op_general_object_delete */ - /** * Property invocation order during [[DefaultValue]] operation with string hint */ @@ -247,7 +104,7 @@ ecma_op_general_object_default_value (ecma_object_t *obj_p, /**< the object */ ecma_object_t *call_func_p = ecma_get_object_from_value (exotic_to_prim); ecma_value_t argument = ecma_make_magic_string_value (hints[hint]); - ecma_value_t result = ecma_op_function_call (call_func_p, obj_value, &argument, 1); + ecma_value_t result = ecma_internal_method_call (call_func_p, obj_value, &argument, 1); ecma_free_value (exotic_to_prim); @@ -316,7 +173,7 @@ ecma_op_general_object_ordinary_value (ecma_object_t *obj_p, /**< the object */ { ecma_object_t *func_obj_p = ecma_get_object_from_value (function_value); - call_completion = ecma_op_function_call (func_obj_p, ecma_make_object_value (obj_p), NULL, 0); + call_completion = ecma_internal_method_call (func_obj_p, ecma_make_object_value (obj_p), NULL, 0); } ecma_free_value (function_value); @@ -334,426 +191,272 @@ ecma_op_general_object_ordinary_value (ecma_object_t *obj_p, /**< the object */ } /* ecma_op_general_object_ordinary_value */ /** - * Special types for ecma_op_general_object_define_own_property. - */ -typedef enum -{ - ECMA_OP_OBJECT_DEFINE_GENERIC = 1, /**< generic property */ - ECMA_OP_OBJECT_DEFINE_ACCESSOR = 0, /**< accessor property */ - ECMA_OP_OBJECT_DEFINE_DATA = ECMA_PROPERTY_FLAG_DATA /**< data property */ -} ecma_op_object_define_own_property_type_t; - -/** - * [[DefineOwnProperty]] ecma general object's operation + * ValidateAndApplyPropertyDescriptor abstract operation * * See also: - * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 - * ECMA-262 v5, 8.12.9 + * ECMAScript v12, 10.1.6.3 * - * @return ecma value - * Returned value must be freed with ecma_free_value + * @return bool */ -ecma_value_t -ecma_op_general_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 */ +bool +ecma_op_validate_and_apply_property_descriptor (ecma_object_t *object_p, /**< object */ + ecma_string_t *prop_name_p, /**< property name */ + const ecma_property_descriptor_t *desc_p, /**< target descriptor */ + const ecma_property_descriptor_t *current_p, /**< current property */ + bool is_extensible) /**< true - if target object is extensible + false - otherwise */ { -#if JERRY_BUILTIN_PROXY - if (ECMA_OBJECT_IS_PROXY (object_p)) - { - return ecma_proxy_object_define_own_property (object_p, property_name_p, property_desc_p); - } -#endif /* JERRY_BUILTIN_PROXY */ - - JERRY_ASSERT (object_p != NULL && !ecma_is_lexical_environment (object_p)); - JERRY_ASSERT (!ecma_op_object_is_fast_array (object_p)); - JERRY_ASSERT (property_name_p != NULL); + JERRY_ASSERT (desc_p != NULL); + JERRY_ASSERT (object_p == NULL || !ECMA_OBJECT_IS_PROXY (object_p)); - uint8_t property_desc_type = ECMA_OP_OBJECT_DEFINE_GENERIC; + const uint32_t accessor_desc_flags = (JERRY_PROP_IS_SET_DEFINED | JERRY_PROP_IS_GET_DEFINED); + const uint32_t data_desc_flags = (JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_WRITABLE_DEFINED); - if (property_desc_p->flags & (JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_WRITABLE_DEFINED)) - { - /* A property descriptor cannot be both named data and named accessor. */ - JERRY_ASSERT ((property_desc_p->flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED)) - != (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED)); - property_desc_type = ECMA_OP_OBJECT_DEFINE_DATA; - } - else if (property_desc_p->flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED)) - { - JERRY_ASSERT (!(property_desc_p->flags & JERRY_PROP_IS_WRITABLE_DEFINED)); - property_desc_type = ECMA_OP_OBJECT_DEFINE_ACCESSOR; - } + bool desc_is_accessor = (desc_p->flags & accessor_desc_flags) != 0; + bool desc_is_data = (desc_p->flags & data_desc_flags) != 0; - /* These three asserts ensures that a new property is created with the appropriate default flags. - * E.g. if JERRY_PROP_IS_CONFIGURABLE_DEFINED is false, the newly created property must be non-configurable. */ - JERRY_ASSERT ((property_desc_p->flags & JERRY_PROP_IS_CONFIGURABLE_DEFINED) - || !(property_desc_p->flags & JERRY_PROP_IS_CONFIGURABLE)); - JERRY_ASSERT ((property_desc_p->flags & JERRY_PROP_IS_ENUMERABLE_DEFINED) - || !(property_desc_p->flags & JERRY_PROP_IS_ENUMERABLE)); - JERRY_ASSERT ((property_desc_p->flags & JERRY_PROP_IS_WRITABLE_DEFINED) - || !(property_desc_p->flags & JERRY_PROP_IS_WRITABLE)); - - /* 1. */ - ecma_extended_property_ref_t ext_property_ref = { .property_ref.value_p = NULL, .property_p = NULL }; - ecma_property_t current_prop; - - current_prop = ecma_op_object_get_own_property (object_p, - property_name_p, - &ext_property_ref.property_ref, - ECMA_PROPERTY_GET_VALUE | ECMA_PROPERTY_GET_EXT_REFERENCE); - - if (!ECMA_PROPERTY_IS_FOUND (current_prop)) + /* 2. */ + if (!ecma_property_descriptor_found (current_p)) { - JERRY_ASSERT (current_prop == ECMA_PROPERTY_TYPE_NOT_FOUND - || current_prop == ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP); - - /* 3. */ - if (!ecma_op_ordinary_object_is_extensible (object_p)) + /* 2.a */ + if (!is_extensible) { - /* 2. */ - return ECMA_REJECT_WITH_FORMAT (property_desc_p->flags & JERRY_PROP_SHOULD_THROW, - "Cannot define property '%', object is not extensible", - ecma_make_prop_name_value (property_name_p)); + return false; } - /* 4. */ - uint8_t prop_attributes = (uint8_t) (property_desc_p->flags & ECMA_PROPERTY_FLAGS_MASK); - - if (property_desc_type != ECMA_OP_OBJECT_DEFINE_ACCESSOR) + if (object_p != NULL) { - /* a. */ - JERRY_ASSERT (property_desc_type == ECMA_OP_OBJECT_DEFINE_GENERIC - || property_desc_type == ECMA_OP_OBJECT_DEFINE_DATA); + uint8_t prop_attributes = + (uint8_t) (desc_p->flags & (JERRY_PROP_IS_CONFIGURABLE | JERRY_PROP_IS_ENUMERABLE | JERRY_PROP_IS_WRITABLE)); - ecma_property_value_t *new_prop_value_p = - ecma_create_named_data_property (object_p, property_name_p, prop_attributes, NULL); + /* 2.c */ + if (desc_is_data || !desc_is_accessor) + { + /* 2.c.i */ + ecma_property_value_t *value_p = ecma_create_named_data_property (object_p, prop_name_p, prop_attributes, NULL); - JERRY_ASSERT ((property_desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED) - || ecma_is_value_undefined (property_desc_p->value)); + value_p->value = ecma_copy_value_if_not_object (desc_p->value); + } + /* 2.d */ + else + { + /* 2.d.i */ + JERRY_ASSERT (desc_is_accessor); - new_prop_value_p->value = ecma_copy_value_if_not_object (property_desc_p->value); - } - else - { - /* b. */ - ecma_create_named_accessor_property (object_p, - property_name_p, - property_desc_p->get_p, - property_desc_p->set_p, - prop_attributes, - NULL); + ecma_object_t *getter_p = ecma_property_descriptor_accessor_getter (desc_p); + ecma_object_t *setter_p = ecma_property_descriptor_accessor_setter (desc_p); + /* 2.d.ii */ + ecma_create_named_accessor_property (object_p, prop_name_p, getter_p, setter_p, prop_attributes, NULL); + } } - return ECMA_VALUE_TRUE; + return true; } - /* 6. */ - const bool is_current_configurable = ecma_is_property_configurable (current_prop); - - /* 7. a., b. */ - bool is_enumerable = (property_desc_p->flags & JERRY_PROP_IS_ENUMERABLE) != 0; - if (!is_current_configurable - && ((property_desc_p->flags & JERRY_PROP_IS_CONFIGURABLE) - || ((property_desc_p->flags & JERRY_PROP_IS_ENUMERABLE_DEFINED) - && (is_enumerable != ecma_is_property_enumerable (current_prop))))) + /* 3. */ + if (desc_p->flags == 0) { - if (ECMA_PROPERTY_IS_VIRTUAL (current_prop)) - { - ecma_free_value (ext_property_ref.property_ref.virtual_value); - } - - return ecma_raise_property_redefinition (property_name_p, property_desc_p->flags); + return true; } - if (ECMA_PROPERTY_IS_VIRTUAL (current_prop)) - { - bool writable_check_failed = (property_desc_p->flags & JERRY_PROP_IS_WRITABLE); - -#if JERRY_MODULE_SYSTEM - if (ecma_object_class_is (object_p, ECMA_OBJECT_CLASS_MODULE_NAMESPACE)) - { - if (JERRY_UNLIKELY (ext_property_ref.property_ref.virtual_value == ECMA_VALUE_UNINITIALIZED)) - { - return ecma_raise_reference_error (ECMA_ERR_LET_CONST_NOT_INITIALIZED); - } + bool target_is_configurable = ((desc_p->flags & (JERRY_PROP_IS_CONFIGURABLE_DEFINED | JERRY_PROP_IS_CONFIGURABLE)) + == (JERRY_PROP_IS_CONFIGURABLE_DEFINED | JERRY_PROP_IS_CONFIGURABLE)); - if (property_desc_p->flags & JERRY_PROP_IS_WRITABLE_DEFINED) - { - writable_check_failed = ((property_desc_p->flags ^ current_prop) & JERRY_PROP_IS_WRITABLE) != 0; - } - } - else + /* 4. */ + if (!ecma_property_descriptor_is_configurable (current_p)) + { + if (target_is_configurable) { - JERRY_ASSERT (!is_current_configurable && !ecma_is_property_writable (current_prop)); + return false; } -#else /* !JERRY_MODULE_SYSTEM */ - JERRY_ASSERT (!is_current_configurable && !ecma_is_property_writable (current_prop)); -#endif /* JERRY_MODULE_SYSTEM */ - - ecma_value_t result = ECMA_VALUE_TRUE; - if (property_desc_type == ECMA_OP_OBJECT_DEFINE_ACCESSOR || writable_check_failed - || ((property_desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED) - && !ecma_op_same_value (property_desc_p->value, ext_property_ref.property_ref.virtual_value))) + if ((desc_p->flags & JERRY_PROP_IS_ENUMERABLE_DEFINED) + && (ecma_property_descriptor_is_enumerable (current_p) != !!(desc_p->flags & JERRY_PROP_IS_ENUMERABLE))) { - result = ecma_raise_property_redefinition (property_name_p, property_desc_p->flags); + return false; } - - ecma_free_value (ext_property_ref.property_ref.virtual_value); - return result; } - /* 8. */ - if (property_desc_type == ECMA_OP_OBJECT_DEFINE_GENERIC) - { - /* No action required. */ - } - else if (JERRY_LIKELY (property_desc_type == (current_prop & ECMA_PROPERTY_FLAG_DATA))) - { - /* If property is configurable, there is no need for checks. */ - if (JERRY_UNLIKELY (!is_current_configurable)) - { - if (property_desc_type == ECMA_OP_OBJECT_DEFINE_DATA) - { - /* 10. a. i. & ii. */ - if (!ecma_is_property_writable (current_prop) - && ((property_desc_p->flags & JERRY_PROP_IS_WRITABLE) - || ((property_desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED) - && !ecma_op_same_value (property_desc_p->value, ext_property_ref.property_ref.value_p->value)))) - { - return ecma_raise_property_redefinition (property_name_p, property_desc_p->flags); - } - } - else - { - /* 11. */ + bool desc_is_generic = !desc_is_data && !desc_is_accessor; + bool current_is_virtual = (current_p->flags & ECMA_PROP_DESC_VIRTUAL); + bool current_is_data = ecma_property_descriptor_is_data_descriptor (current_p); - /* a. */ - ecma_property_value_t *value_p = ext_property_ref.property_ref.value_p; + ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (current_p->u.property_p); - ecma_getter_setter_pointers_t *get_set_pair_p = ecma_get_named_accessor_property (value_p); - jmem_cpointer_t prop_desc_getter_cp, prop_desc_setter_cp; - ECMA_SET_POINTER (prop_desc_getter_cp, property_desc_p->get_p); - ECMA_SET_POINTER (prop_desc_setter_cp, property_desc_p->set_p); - - if (((property_desc_p->flags & JERRY_PROP_IS_GET_DEFINED) && prop_desc_getter_cp != get_set_pair_p->getter_cp) - || ((property_desc_p->flags & JERRY_PROP_IS_SET_DEFINED) - && prop_desc_setter_cp != get_set_pair_p->setter_cp)) - { - /* i., ii. */ - return ecma_raise_property_redefinition (property_name_p, property_desc_p->flags); - } - } - } - } - else + /* 5. */ + if (desc_is_generic) { - /* 9. */ - if (!is_current_configurable) + if (object_p != NULL && !current_is_virtual) { - /* a. */ - return ecma_raise_property_redefinition (property_name_p, property_desc_p->flags); + ecma_set_property_configurable_and_enumerable_flags (current_p->u.property_p, desc_p->flags); } - ecma_property_value_t *value_p = ext_property_ref.property_ref.value_p; - - if (property_desc_type == ECMA_OP_OBJECT_DEFINE_ACCESSOR) - { - JERRY_ASSERT (current_prop & ECMA_PROPERTY_FLAG_DATA); - ecma_free_value_if_not_object (value_p->value); - -#if JERRY_CPOINTER_32_BIT - ecma_getter_setter_pointers_t *getter_setter_pair_p; - getter_setter_pair_p = jmem_pools_alloc (sizeof (ecma_getter_setter_pointers_t)); - getter_setter_pair_p->getter_cp = JMEM_CP_NULL; - getter_setter_pair_p->setter_cp = JMEM_CP_NULL; - ECMA_SET_NON_NULL_POINTER (value_p->getter_setter_pair_cp, getter_setter_pair_p); -#else /* !JERRY_CPOINTER_32_BIT */ - value_p->getter_setter_pair.getter_cp = JMEM_CP_NULL; - value_p->getter_setter_pair.setter_cp = JMEM_CP_NULL; -#endif /* JERRY_CPOINTER_32_BIT */ - } - else - { - JERRY_ASSERT (!(current_prop & ECMA_PROPERTY_FLAG_DATA)); -#if JERRY_CPOINTER_32_BIT - ecma_getter_setter_pointers_t *getter_setter_pair_p; - getter_setter_pair_p = ECMA_GET_NON_NULL_POINTER (ecma_getter_setter_pointers_t, value_p->getter_setter_pair_cp); - jmem_pools_free (getter_setter_pair_p, sizeof (ecma_getter_setter_pointers_t)); -#endif /* JERRY_CPOINTER_32_BIT */ - value_p->value = ECMA_VALUE_UNDEFINED; - } - - /* Update flags */ - ecma_property_t prop_flags = *(ext_property_ref.property_p); - prop_flags = (ecma_property_t) (prop_flags & ~ECMA_PROPERTY_FLAG_WRITABLE); - prop_flags ^= ECMA_PROPERTY_FLAG_DATA; - *(ext_property_ref.property_p) = prop_flags; + return true; } - /* 12. */ - if (property_desc_type == ECMA_OP_OBJECT_DEFINE_DATA) + /* 6. */ + if (current_is_data != desc_is_data) { - JERRY_ASSERT (ECMA_PROPERTY_IS_RAW_DATA (*ext_property_ref.property_p)); - - if (property_desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED) - { - ecma_named_data_property_assign_value (object_p, ext_property_ref.property_ref.value_p, property_desc_p->value); - } - - if (property_desc_p->flags & JERRY_PROP_IS_WRITABLE_DEFINED) + if (current_is_virtual) { - ecma_set_property_writable_attr (ext_property_ref.property_p, (property_desc_p->flags & JERRY_PROP_IS_WRITABLE)); + return false; } - } - else if (property_desc_type == ECMA_OP_OBJECT_DEFINE_ACCESSOR) - { - JERRY_ASSERT (!(*ext_property_ref.property_p & ECMA_PROPERTY_FLAG_DATA)); - if (property_desc_p->flags & JERRY_PROP_IS_GET_DEFINED) + /* 6.a */ + if (!ecma_property_descriptor_is_configurable (current_p)) { - ecma_set_named_accessor_property_getter (object_p, ext_property_ref.property_ref.value_p, property_desc_p->get_p); + return false; } - if (property_desc_p->flags & JERRY_PROP_IS_SET_DEFINED) + if (object_p != NULL) { - ecma_set_named_accessor_property_setter (object_p, ext_property_ref.property_ref.value_p, property_desc_p->set_p); - } - } + /* 6.b */ + if (current_is_data) + { + ecma_object_t *getter_p = ecma_property_descriptor_accessor_getter (desc_p); + ecma_object_t *setter_p = ecma_property_descriptor_accessor_setter (desc_p); - if (property_desc_p->flags & JERRY_PROP_IS_ENUMERABLE_DEFINED) - { - ecma_set_property_enumerable_attr (ext_property_ref.property_p, - (property_desc_p->flags & JERRY_PROP_IS_ENUMERABLE)); - } +#if JERRY_CPOINTER_32_BIT + ecma_getter_setter_pointers_t *getter_setter_pair_p = jmem_pools_alloc (sizeof (ecma_getter_setter_pointers_t)); +#else /* !JERRY_CPOINTER_32_BIT */ + ecma_getter_setter_pointers_t *getter_setter_pair_p = &prop_value_p->getter_setter_pair; +#endif /* JERRY_CPOINTER_32_BIT */ - if (property_desc_p->flags & JERRY_PROP_IS_CONFIGURABLE_DEFINED) - { - ecma_set_property_configurable_attr (ext_property_ref.property_p, - (property_desc_p->flags & JERRY_PROP_IS_CONFIGURABLE)); - } + ecma_free_value_if_not_object (prop_value_p->value); + *current_p->u.property_p = + (uint8_t) (*current_p->u.property_p & ~(ECMA_PROPERTY_FLAG_DATA | ECMA_PROPERTY_FLAG_WRITABLE)); - return ECMA_VALUE_TRUE; -} /* ecma_op_general_object_define_own_property */ +#if JERRY_CPOINTER_32_BIT + ECMA_SET_NON_NULL_POINTER (prop_value_p->getter_setter_pair_cp, getter_setter_pair_p); +#endif /* JERRY_CPOINTER_32_BIT */ -#if JERRY_ESNEXT -/** - * The IsCompatiblePropertyDescriptor method for Proxy object internal methods - * - * See also: - * ECMAScript v6, 9.1.6.2 - * - * @return bool - */ -bool -ecma_op_is_compatible_property_descriptor (const ecma_property_descriptor_t *desc_p, /**< target descriptor */ - const ecma_property_descriptor_t *current_p, /**< current descriptor */ - bool is_extensible) /**< true - if target object is extensible - false - otherwise */ -{ - JERRY_ASSERT (desc_p != NULL); + ECMA_SET_POINTER (getter_setter_pair_p->getter_cp, getter_p); + ECMA_SET_POINTER (getter_setter_pair_p->setter_cp, setter_p); + } + else + { + /* 6.c */ + ecma_value_t data_desc_value = ecma_copy_value_if_not_object (desc_p->value); +#if JERRY_CPOINTER_32_BIT + ecma_getter_setter_pointers_t *getter_setter_pair_p = + ECMA_GET_NON_NULL_POINTER (ecma_getter_setter_pointers_t, prop_value_p->getter_setter_pair_cp); + jmem_pools_free (getter_setter_pair_p, sizeof (ecma_getter_setter_pointers_t)); +#endif /* JERRY_CPOINTER_32_BIT */ - /* 2. */ - if (current_p == NULL) - { - return is_extensible; - } + *current_p->u.property_p |= ECMA_PROPERTY_FLAG_DATA; + prop_value_p->value = data_desc_value; - /* 3. */ - if (desc_p->flags == 0) - { - return true; - } - - /* 4. */ - if ((current_p->flags & desc_p->flags) == desc_p->flags) - { - if ((current_p->flags & JERRY_PROP_IS_VALUE_DEFINED) && ecma_op_same_value (current_p->value, desc_p->value)) - { - return true; - } + if (desc_p->flags & JERRY_PROP_IS_WRITABLE_DEFINED) + { + ecma_set_property_writable_attr (current_p->u.property_p, desc_p->flags & JERRY_PROP_IS_WRITABLE); + } + } - if ((current_p->flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED) && current_p->get_p == desc_p->get_p - && current_p->set_p == desc_p->set_p)) - { + ecma_set_property_configurable_and_enumerable_flags (current_p->u.property_p, desc_p->flags); return true; } - } - - /* 5. */ - if (!(current_p->flags & JERRY_PROP_IS_CONFIGURABLE)) - { - if (desc_p->flags & JERRY_PROP_IS_CONFIGURABLE) - { - return false; - } - if ((desc_p->flags & JERRY_PROP_IS_ENUMERABLE_DEFINED) - && ((current_p->flags & JERRY_PROP_IS_ENUMERABLE) != (desc_p->flags & JERRY_PROP_IS_ENUMERABLE))) - { - return false; - } - } - - const uint32_t accessor_desc_flags = (JERRY_PROP_IS_SET_DEFINED | JERRY_PROP_IS_GET_DEFINED); - const uint32_t data_desc_flags = (JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_WRITABLE_DEFINED); - - bool desc_is_accessor = (desc_p->flags & accessor_desc_flags) != 0; - bool desc_is_data = (desc_p->flags & data_desc_flags) != 0; - bool current_is_data = (current_p->flags & data_desc_flags) != 0; - /* 6. */ - if (!desc_is_accessor && !desc_is_data) - { return true; } /* 7. */ - if (current_is_data != desc_is_data) - { - return (current_p->flags & JERRY_PROP_IS_CONFIGURABLE) != 0; - } - - /* 8. */ if (current_is_data) { - if (!(current_p->flags & JERRY_PROP_IS_CONFIGURABLE)) + /* 7.a */ + if (!ecma_property_descriptor_is_configurable (current_p) && !ecma_property_descriptor_is_writable (current_p)) { - if (!(current_p->flags & JERRY_PROP_IS_WRITABLE) && (desc_p->flags & JERRY_PROP_IS_WRITABLE)) + bool target_is_writable = ((desc_p->flags & (JERRY_PROP_IS_WRITABLE_DEFINED | JERRY_PROP_IS_WRITABLE)) + == (JERRY_PROP_IS_WRITABLE_DEFINED | JERRY_PROP_IS_WRITABLE)); + /* 7.a.i */ + if (target_is_writable + || ((desc_p->flags & JERRY_PROP_IS_WRITABLE_DEFINED) + && ((desc_p->flags ^ (current_p->flags)) & JERRY_PROP_IS_WRITABLE) != 0)) + { return false; } - if (!(current_p->flags & JERRY_PROP_IS_WRITABLE) && (desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED) - && !ecma_op_same_value (desc_p->value, current_p->value)) + /* 7.a.ii */ + if ((desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED) + && !ecma_op_same_value (desc_p->value, ecma_property_descriptor_value (current_p))) { return false; } } + if (object_p != NULL && !current_is_virtual) + { + if (desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED) + { + ecma_free_value_if_not_object (prop_value_p->value); + prop_value_p->value = ecma_copy_value_if_not_object (desc_p->value); + } + + if (desc_p->flags & JERRY_PROP_IS_WRITABLE_DEFINED) + { + ecma_set_property_writable_attr (current_p->u.property_p, desc_p->flags & JERRY_PROP_IS_WRITABLE); + } + + ecma_set_property_configurable_and_enumerable_flags (current_p->u.property_p, desc_p->flags); + } + return true; } - JERRY_ASSERT ((current_p->flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED)) != 0); + /* 8.a */ + JERRY_ASSERT (!current_is_data); JERRY_ASSERT ((desc_p->flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED)) != 0); - /* 9. */ - if (!(current_p->flags & JERRY_PROP_IS_CONFIGURABLE)) + ecma_object_t *desc_getter_p = ecma_property_descriptor_accessor_getter (desc_p); + ecma_object_t *desc_setter_p = ecma_property_descriptor_accessor_setter (desc_p); + + /* 8.b */ + if (!ecma_property_descriptor_is_configurable (current_p)) { - if ((desc_p->flags & JERRY_PROP_IS_SET_DEFINED) && desc_p->set_p != current_p->set_p) + ecma_object_t *current_getter_p = ecma_property_descriptor_accessor_getter (current_p); + ecma_object_t *current_setter_p = ecma_property_descriptor_accessor_setter (current_p); + + /* 8.b.i */ + if ((desc_p->flags & JERRY_PROP_IS_SET_DEFINED) && desc_setter_p != current_setter_p) { return false; } - if ((desc_p->flags & JERRY_PROP_IS_GET_DEFINED) && desc_p->get_p != current_p->get_p) + /* 8.b.ii */ + if ((desc_p->flags & JERRY_PROP_IS_GET_DEFINED) && desc_getter_p != current_getter_p) { return false; } } + if (object_p != NULL) + { +#if JERRY_CPOINTER_32_BIT + ecma_getter_setter_pointers_t *getter_setter_pair_p = + ECMA_GET_NON_NULL_POINTER (ecma_getter_setter_pointers_t, prop_value_p->getter_setter_pair_cp); + ECMA_SET_NON_NULL_POINTER (prop_value_p->getter_setter_pair_cp, getter_setter_pair_p); +#else /* !JERRY_CPOINTER_32_BIT */ + ecma_getter_setter_pointers_t *getter_setter_pair_p = &prop_value_p->getter_setter_pair; +#endif /* JERRY_CPOINTER_32_BIT */ + + if (desc_p->flags & JERRY_PROP_IS_GET_DEFINED) + { + ECMA_SET_POINTER (getter_setter_pair_p->getter_cp, desc_getter_p); + } + + if (desc_p->flags & JERRY_PROP_IS_SET_DEFINED) + { + ECMA_SET_POINTER (getter_setter_pair_p->setter_cp, desc_setter_p); + } + + ecma_set_property_configurable_and_enumerable_flags (current_p->u.property_p, desc_p->flags); + } + + /* 10. */ return true; -} /* ecma_op_is_compatible_property_descriptor */ +} /* ecma_op_validate_and_apply_property_descriptor */ +#if JERRY_ESNEXT /** * CompletePropertyDescriptor method for proxy internal method * diff --git a/jerry-core/ecma/operations/ecma-objects-general.h b/jerry-core/ecma/operations/ecma-objects-general.h index aea9959d4e..f8748e03fa 100644 --- a/jerry-core/ecma/operations/ecma-objects-general.h +++ b/jerry-core/ecma/operations/ecma-objects-general.h @@ -27,23 +27,20 @@ */ ecma_object_t *ecma_op_create_object_object_noarg (void); -ecma_object_t *ecma_op_create_object_object_noarg_and_set_prototype (ecma_object_t *object_prototype_p); -ecma_value_t ecma_op_general_object_delete (ecma_object_t *obj_p, ecma_string_t *property_name_p, bool is_throw); ecma_value_t ecma_op_general_object_default_value (ecma_object_t *obj_p, ecma_preferred_type_hint_t hint); ecma_value_t ecma_op_general_object_ordinary_value (ecma_object_t *obj_p, ecma_preferred_type_hint_t hint); -ecma_value_t ecma_op_general_object_define_own_property (ecma_object_t *object_p, - ecma_string_t *property_name_p, - const ecma_property_descriptor_t *property_desc_p); #if JERRY_ESNEXT void ecma_op_to_complete_property_descriptor (ecma_property_descriptor_t *desc_p); - -bool ecma_op_is_compatible_property_descriptor (const ecma_property_descriptor_t *desc_p, - const ecma_property_descriptor_t *current_p, - bool is_extensible); #endif /* JERRY_ESNEXT */ +bool ecma_op_validate_and_apply_property_descriptor (ecma_object_t *object_p, + ecma_string_t *prop_name_p, + const ecma_property_descriptor_t *desc_p, + const ecma_property_descriptor_t *current_p, + bool is_extensible); + /** * @} * @} diff --git a/jerry-core/ecma/operations/ecma-objects.c b/jerry-core/ecma/operations/ecma-objects.c index 59b8ecde27..f99279764a 100644 --- a/jerry-core/ecma/operations/ecma-objects.c +++ b/jerry-core/ecma/operations/ecma-objects.c @@ -18,8 +18,11 @@ #include "ecma-arguments-object.h" #include "ecma-array-object.h" #include "ecma-bigint.h" +#include "ecma-bound-function.h" #include "ecma-builtin-helpers.h" #include "ecma-builtins.h" +#include "ecma-class-object.h" +#include "ecma-constructor-function.h" #include "ecma-exceptions.h" #include "ecma-function-object.h" #include "ecma-gc.h" @@ -27,7 +30,9 @@ #include "ecma-helpers.h" #include "ecma-lcache.h" #include "ecma-lex-env.h" +#include "ecma-native-function.h" #include "ecma-objects-general.h" +#include "ecma-ordinary-object.h" #include "ecma-proxy-object.h" #include "ecma-string-object.h" @@ -62,840 +67,328 @@ #endif /* !JERRY_NDEBUG */ /** - * [[GetOwnProperty]] ecma object's operation - * - * See also: - * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 - * - * @return pointer to a property - if it exists, - * NULL (i.e. ecma-undefined) - otherwise. + * Get the virtual function table for the given object */ -ecma_property_t -ecma_op_object_get_own_property (ecma_object_t *object_p, /**< the object */ - ecma_string_t *property_name_p, /**< property name */ - ecma_property_ref_t *property_ref_p, /**< property reference */ - uint32_t options) /**< option bits */ -{ - JERRY_ASSERT (object_p != NULL && !ecma_is_lexical_environment (object_p)); +#define ECMA_OBJECT_INTERNAL_METHOD_TABLE(obj_p) (VTABLE_CONTAINER[ecma_get_object_type (obj_p)]) + +/** + * Container for every virtual table indexed by the proper object type + */ +static const ecma_internal_method_table_t VTABLE_CONTAINER[] = { + ECMA_ORDINARY_OBJ_VTABLE, + ECMA_BUILT_IN_OBJ_VTABLE, + ECMA_CLASS_OBJ_VTABLE, + ECMA_BUILT_IN_CLASS_OBJ_VTABLE, + ECMA_ARRAY_OBJ_VTABLE, + ECMA_BUILT_IN_ARRAY_OBJ_VTABLE, #if JERRY_BUILTIN_PROXY - JERRY_ASSERT (!ECMA_OBJECT_IS_PROXY (object_p)); + ECMA_PROXY_OBJ_VTABLE, #endif /* JERRY_BUILTIN_PROXY */ - JERRY_ASSERT (property_name_p != NULL); - JERRY_ASSERT (options == ECMA_PROPERTY_GET_NO_OPTIONS || property_ref_p != NULL); - - ecma_object_base_type_t base_type = ecma_get_object_base_type (object_p); - - switch (base_type) - { - case ECMA_OBJECT_BASE_TYPE_CLASS: - { - ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; + ECMA_FUNCTION_OBJ_VTABLE, + ECMA_BUILT_IN_FUNCTION_OBJ_VTABLE, + ECMA_BOUND_FUNCTION_OBJ_VTABLE, +#if JERRY_ESNEXT + ECMA_CONSTRUCTOR_FUNCTION_OBJ_VTABLE, +#endif /* JERRY_ESNEXT */ + ECMA_NATIVE_FUNCTION_OBJ_VTABLE, +}; - switch (ext_object_p->u.cls.type) - { - case ECMA_OBJECT_CLASS_STRING: - { - if (ecma_string_is_length (property_name_p)) - { - if (options & ECMA_PROPERTY_GET_VALUE) - { - ecma_value_t prim_value_p = ext_object_p->u.cls.u3.value; - ecma_string_t *prim_value_str_p = ecma_get_string_from_value (prim_value_p); +/** + * Helper function for calling the given object's [[GetPrototypeOf]] internal method + * + * @return ecma_object_t * + */ +extern inline ecma_object_t *JERRY_ATTR_ALWAYS_INLINE +ecma_internal_method_get_prototype_of (ecma_object_t *obj_p) /**< object */ +{ + return ECMA_OBJECT_INTERNAL_METHOD_TABLE (obj_p).get_prototype_of (obj_p); +} /* ecma_internal_method_get_prototype_of */ - lit_utf8_size_t length = ecma_string_get_length (prim_value_str_p); - property_ref_p->virtual_value = ecma_make_uint32_value (length); - } +/** + * Helper function for calling the given object's [[SetPrototypeOf]] internal method + * + * @return ecma value t + */ +extern inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE +ecma_internal_method_set_prototype_of (ecma_object_t *obj_p, /**< base object */ + ecma_value_t proto) /**< prototype object */ +{ + return ECMA_OBJECT_INTERNAL_METHOD_TABLE (obj_p).set_prototype_of (obj_p, proto); +} /* ecma_internal_method_set_prototype_of */ - return ECMA_PROPERTY_VIRTUAL; - } +/** + * Helper function for calling the given object's [[IsExtensible]] internal method + * + * @return ecma value t + */ +extern inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE +ecma_internal_method_is_extensible (ecma_object_t *obj_p) /**< object */ +{ + return ECMA_OBJECT_INTERNAL_METHOD_TABLE (obj_p).is_extensible (obj_p); +} /* ecma_internal_method_is_extensible */ - uint32_t index = ecma_string_get_array_index (property_name_p); +/** + * Helper function for calling the given object's [[PreventExtensions]] internal method + * + * @return ecma value t + */ +extern inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE +ecma_internal_method_prevent_extensions (ecma_object_t *obj_p) /**< object */ +{ + return ECMA_OBJECT_INTERNAL_METHOD_TABLE (obj_p).prevent_extensions (obj_p); +} /* ecma_internal_method_prevent_extensions */ - if (index != ECMA_STRING_NOT_ARRAY_INDEX) - { - ecma_value_t prim_value_p = ext_object_p->u.cls.u3.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)) - { - if (options & ECMA_PROPERTY_GET_VALUE) - { - ecma_char_t char_at_idx = ecma_string_get_char_at_pos (prim_value_str_p, index); - ecma_string_t *char_str_p = ecma_new_ecma_string_from_code_unit (char_at_idx); - property_ref_p->virtual_value = ecma_make_string_value (char_str_p); - } - - return ECMA_PROPERTY_FLAG_ENUMERABLE | ECMA_PROPERTY_VIRTUAL; - } - } - break; - } -#if JERRY_BUILTIN_TYPEDARRAY - /* ES2015 9.4.5.1 */ - case ECMA_OBJECT_CLASS_TYPEDARRAY: - { - if (ecma_prop_name_is_symbol (property_name_p)) - { - break; - } +/** + * Helper function for calling the given object's [[GetOwnProperty]] internal method + * + * @return ecma property reference + */ +extern inline ecma_property_descriptor_t JERRY_ATTR_ALWAYS_INLINE +ecma_internal_method_get_own_property (ecma_object_t *obj_p, /**< the object */ + ecma_string_t *property_name_p) /**< property name */ +{ + return ECMA_OBJECT_INTERNAL_METHOD_TABLE (obj_p).get_own_property (obj_p, property_name_p); +} /* ecma_internal_method_get_own_property */ - uint32_t index = ecma_string_get_array_index (property_name_p); +/** + * Helper function for calling the given object's [[DefineOwnProperty]] internal method + * + * @return ecma value t + */ +extern inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE +ecma_internal_method_define_own_property (ecma_object_t *obj_p, /**< the object */ + ecma_string_t *property_name_p, /**< property name */ + const ecma_property_descriptor_t *property_desc_p) /**< property + * descriptor */ +{ + return ECMA_OBJECT_INTERNAL_METHOD_TABLE (obj_p).define_own_property (obj_p, property_name_p, property_desc_p); +} /* ecma_internal_method_define_own_property */ - if (index == ECMA_STRING_NOT_ARRAY_INDEX) - { - JERRY_ASSERT (index == UINT32_MAX); +/** + * Helper function for calling the given object's [[HasProperty]] internal method + * + * @return ecma value t + */ +extern inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE +ecma_internal_method_has_property (ecma_object_t *obj_p, /**< the object */ + ecma_string_t *property_name_p) /**< property name */ +{ + return ECMA_OBJECT_INTERNAL_METHOD_TABLE (obj_p).has_property (obj_p, property_name_p); +} /* ecma_internal_method_has_property */ - if (!ecma_typedarray_is_element_index (property_name_p)) - { - break; - } - } +/** + * Helper function for calling the given object's [[Get]] internal method + * + * @return ecma value t + */ +extern inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE +ecma_internal_method_get (ecma_object_t *obj_p, /**< target object */ + ecma_string_t *property_name_p, /**< property name */ + ecma_value_t base_value) /**< base value */ +{ + return ECMA_OBJECT_INTERNAL_METHOD_TABLE (obj_p).get (obj_p, property_name_p, base_value); +} /* ecma_internal_method_get */ - ecma_typedarray_info_t info = ecma_typedarray_get_info (object_p); - ecma_value_t value = ecma_get_typedarray_element (&info, index); +/** + * Helper function for calling the given object's [[Set]] internal method + * + * @return ecma value t + */ +extern inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE +ecma_internal_method_set (ecma_object_t *obj_p, /**< the object */ + ecma_string_t *property_name_p, /**< property name */ + ecma_value_t value, /**< ecma value */ + ecma_value_t receiver, /**< receiver */ + bool is_throw) /**< flag that controls failure handling */ +{ + return ECMA_OBJECT_INTERNAL_METHOD_TABLE (obj_p).set (obj_p, property_name_p, value, receiver, is_throw); +} /* ecma_internal_method_set */ - if (ECMA_IS_VALUE_ERROR (value)) - { - return ECMA_PROPERTY_TYPE_NOT_FOUND_AND_THROW; - } +/** + * Helper function for calling the given object's [[Delete]] internal method + * + * @return ecma value t + */ +extern inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE +ecma_internal_method_delete (ecma_object_t *obj_p, /**< the object */ + ecma_string_t *property_name_p, /**< property name */ + bool is_strict) /**< flag that controls failure handling */ +{ + return ECMA_OBJECT_INTERNAL_METHOD_TABLE (obj_p).delete(obj_p, property_name_p, is_strict); +} /* ecma_internal_method_delete */ - if (JERRY_UNLIKELY (ecma_is_value_undefined (value))) - { - return ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP; - } +/** + * Helper function for calling the given object's [[OwnPropertyKeys]] internal method + * + * @return ecma collection + */ +extern inline ecma_collection_t *JERRY_ATTR_ALWAYS_INLINE +ecma_internal_method_own_property_keys (ecma_object_t *obj_p, /**< object */ + jerry_property_filter_t filter) /**< name filters */ +{ + return ECMA_OBJECT_INTERNAL_METHOD_TABLE (obj_p).own_property_keys (obj_p, filter); +} /* ecma_internal_method_own_property_keys */ - if (options & ECMA_PROPERTY_GET_VALUE) - { - property_ref_p->virtual_value = value; - } - else - { - ecma_fast_free_value (value); - } +/** + * @return the result of the function call. + */ +extern inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE +ecma_internal_method_call (ecma_object_t *obj_p, /**< function object */ + ecma_value_t this_value, /**< 'this' argument's value */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< length of arguments list */ +{ + ECMA_CHECK_STACK_USAGE (); + return ECMA_OBJECT_INTERNAL_METHOD_TABLE (obj_p).call (obj_p, this_value, arguments_list_p, arguments_list_len); +} /* ecma_internal_method_call */ - return ECMA_PROPERTY_ENUMERABLE_WRITABLE | ECMA_PROPERTY_VIRTUAL; - } -#endif /* JERRY_BUILTIN_TYPEDARRAY */ -#if JERRY_MODULE_SYSTEM - case ECMA_OBJECT_CLASS_MODULE_NAMESPACE: - { - if (JERRY_UNLIKELY (ecma_prop_name_is_symbol (property_name_p))) - { - if (!ecma_op_compare_string_to_global_symbol (property_name_p, LIT_GLOBAL_SYMBOL_TO_STRING_TAG)) - { - return ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP; - } - - /* ECMA-262 v11, 26.3.1 */ - if (options & ECMA_PROPERTY_GET_VALUE) - { - property_ref_p->virtual_value = ecma_make_magic_string_value (LIT_MAGIC_STRING_MODULE_UL); - } - - return ECMA_PROPERTY_VIRTUAL; - } +/** + * @return the result of the function call. + */ +extern inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE +ecma_internal_method_validated_call (ecma_value_t callee, /**< callee */ + ecma_value_t this_value, /**< 'this' argument's value */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< length of arguments list */ +{ + if (!ecma_is_value_object (callee)) + { + return ecma_raise_type_error (ECMA_ERR_EXPECTED_A_FUNCTION); + } - ecma_property_t *property_p = ecma_find_named_property (object_p, property_name_p); + ecma_object_t *callee_p = ecma_get_object_from_value (callee); - if (property_p == NULL) - { - return ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP; - } + return ecma_internal_method_call (callee_p, this_value, arguments_list_p, arguments_list_len); +} /* ecma_internal_method_validated_call */ - JERRY_ASSERT (ECMA_PROPERTY_IS_RAW (*property_p)); +/** + * @return the result of the function call. + */ +extern inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE +ecma_internal_method_construct (ecma_object_t *obj_p, /**< function object */ + ecma_object_t *new_target_p, /**< 'this' argument's value */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< length of arguments list */ +{ + ECMA_CHECK_STACK_USAGE (); + return ECMA_OBJECT_INTERNAL_METHOD_TABLE (obj_p).construct (obj_p, + new_target_p, + arguments_list_p, + arguments_list_len); +} /* ecma_internal_method_construct */ - if (*property_p & ECMA_PROPERTY_FLAG_DATA) - { - if (options & ECMA_PROPERTY_GET_EXT_REFERENCE) - { - ((ecma_extended_property_ref_t *) property_ref_p)->property_p = property_p; - } +/** + * Helper function for calling the given object's [[Delete]] internal method + * + * @return ecma value t + */ +extern inline void JERRY_ATTR_ALWAYS_INLINE +ecma_internal_method_list_lazy_property_keys (ecma_object_t *obj_p, /**< a built-in object */ + ecma_collection_t *prop_names_p, /**< prop name collection */ + ecma_property_counter_t *prop_counter_p, /**< property counters */ + jerry_property_filter_t filter) /**< name filters */ +{ + ECMA_OBJECT_INTERNAL_METHOD_TABLE (obj_p).list_lazy_property_keys (obj_p, prop_names_p, prop_counter_p, filter); +} /* ecma_internal_method_list_lazy_property_keys */ - if (property_ref_p != NULL) - { - property_ref_p->value_p = ECMA_PROPERTY_VALUE_PTR (property_p); - } +/** + * Helper function for calling the given object's [[Delete]] internal method + * + * @return ecma value t + */ +extern inline void JERRY_ATTR_ALWAYS_INLINE +ecma_internal_method_delete_lazy_property (ecma_object_t *obj_p, /**< the object */ + ecma_string_t *property_name_p) /**< property name */ +{ + ECMA_OBJECT_INTERNAL_METHOD_TABLE (obj_p).delete_lazy_property (obj_p, property_name_p); +} /* ecma_internal_method_delete_lazy_property */ - return *property_p; - } +/** + * Helper function for calling the given object's find method + * + * @return ecma value t + */ +ecma_value_t +ecma_op_object_find (ecma_object_t *obj_p, /**< target object */ + ecma_string_t *property_name_p, /**< property name */ + ecma_value_t receiver) /**< base value */ +{ + ecma_property_descriptor_t prop_desc; + ecma_internal_has_property_cb_t has_cb = ECMA_OBJECT_INTERNAL_METHOD_TABLE (obj_p).has_property; - if (options & ECMA_PROPERTY_GET_VALUE) - { - ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); - prop_value_p = ecma_get_property_value_from_named_reference (prop_value_p); - property_ref_p->virtual_value = ecma_fast_copy_value (prop_value_p->value); - } + while (has_cb == ecma_ordinary_object_has_property) + { + /* 2. */ + prop_desc = ecma_internal_method_get_own_property (obj_p, property_name_p); - return ECMA_PROPERTY_ENUMERABLE_WRITABLE | ECMA_PROPERTY_VIRTUAL; - } -#endif /* JERRY_MODULE_SYSTEM */ - } - break; - } - case ECMA_OBJECT_BASE_TYPE_ARRAY: + if (ecma_property_descriptor_error (&prop_desc)) { - ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; - - if (ecma_string_is_length (property_name_p)) - { - if (options & ECMA_PROPERTY_GET_VALUE) - { - property_ref_p->virtual_value = ecma_make_uint32_value (ext_object_p->u.array.length); - } - - uint32_t length_prop = ext_object_p->u.array.length_prop_and_hole_count; - return length_prop & (ECMA_PROPERTY_FLAG_WRITABLE | ECMA_PROPERTY_VIRTUAL); - } - - if (ecma_op_array_is_fast_array (ext_object_p)) - { - uint32_t index = ecma_string_get_array_index (property_name_p); - - if (index != ECMA_STRING_NOT_ARRAY_INDEX) - { - if (JERRY_LIKELY (index < ext_object_p->u.array.length)) - { - ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp); - - if (ecma_is_value_array_hole (values_p[index])) - { - return ECMA_PROPERTY_TYPE_NOT_FOUND; - } - - if (options & ECMA_PROPERTY_GET_VALUE) - { - property_ref_p->virtual_value = ecma_fast_copy_value (values_p[index]); - } - - return ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE | ECMA_PROPERTY_VIRTUAL; - } - } - - return ECMA_PROPERTY_TYPE_NOT_FOUND; - } - - break; + return ECMA_VALUE_ERROR; } - default: + + /* 3. */ + if (ecma_property_descriptor_found (&prop_desc)) { - break; + return ecma_property_descriptor_get (&prop_desc, receiver); } - } - ecma_property_t *property_p = ecma_find_named_property (object_p, property_name_p); - ecma_object_type_t type = ecma_get_object_type (object_p); + /* 3.a */ + jmem_cpointer_t proto_cp = ecma_object_get_prototype_of (obj_p); - if (property_p == NULL) - { - switch (type) + /* 3.b */ + if (proto_cp == JMEM_CP_NULL) { - case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION: - { - if (ecma_builtin_function_is_routine (object_p)) - { - property_p = ecma_builtin_routine_try_to_instantiate_property (object_p, property_name_p); - break; - } - /* FALLTHRU */ - } - case ECMA_OBJECT_TYPE_BUILT_IN_GENERAL: - case ECMA_OBJECT_TYPE_BUILT_IN_CLASS: - case ECMA_OBJECT_TYPE_BUILT_IN_ARRAY: - { - property_p = ecma_builtin_try_to_instantiate_property (object_p, property_name_p); - break; - } - case ECMA_OBJECT_TYPE_CLASS: - { - if (((ecma_extended_object_t *) object_p)->u.cls.type == ECMA_OBJECT_CLASS_ARGUMENTS) - { - property_p = ecma_op_arguments_object_try_to_lazy_instantiate_property (object_p, property_name_p); - } - break; - } - case ECMA_OBJECT_TYPE_FUNCTION: - { -#if !JERRY_ESNEXT - if (ecma_string_is_length (property_name_p)) - { - 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_VIRTUAL; - } -#endif /* !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; - } - default: - { - break; - } + return ECMA_VALUE_NOT_FOUND; } - if (property_p == NULL) - { - return ECMA_PROPERTY_TYPE_NOT_FOUND; - } + /* 3.c */ + obj_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, proto_cp); + has_cb = ECMA_OBJECT_INTERNAL_METHOD_TABLE (obj_p).has_property; } - else if (type == ECMA_OBJECT_TYPE_CLASS - && ((ecma_extended_object_t *) object_p)->u.cls.type == ECMA_OBJECT_CLASS_ARGUMENTS - && (((ecma_extended_object_t *) object_p)->u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED)) - { - ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; - - uint32_t index = ecma_string_get_array_index (property_name_p); - - if (index < ext_object_p->u.cls.u2.formal_params_number) - { - ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) ext_object_p; - - ecma_value_t *argv_p = (ecma_value_t *) (mapped_arguments_p + 1); - - if (!ecma_is_value_empty (argv_p[index]) && argv_p[index] != ECMA_VALUE_ARGUMENT_NO_TRACK) - { -#if JERRY_LCACHE - /* Mapped arguments initialized properties MUST not be lcached */ - if (ecma_is_property_lcached (property_p)) - { - jmem_cpointer_t prop_name_cp; - - 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 /* 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); - } - } - } + JERRY_ASSERT (has_cb); + ecma_value_t has_result = has_cb (obj_p, property_name_p); - if (options & ECMA_PROPERTY_GET_EXT_REFERENCE) + if (ecma_is_value_true (has_result)) { - ((ecma_extended_property_ref_t *) property_ref_p)->property_p = property_p; + return ecma_internal_method_get (obj_p, property_name_p, ecma_make_object_value (obj_p)); } - if (property_ref_p != NULL) + if (ecma_is_value_false (has_result)) { - property_ref_p->value_p = ECMA_PROPERTY_VALUE_PTR (property_p); + return ECMA_VALUE_NOT_FOUND; } - return *property_p; -} /* ecma_op_object_get_own_property */ - -/** - * Generic [[HasProperty]] operation - * - * See also: - * ECMAScript v6, 9.1.7.1 - * - * @return ECMA_VALUE_ERROR - if the operation fails - * ECMA_VALUE_{TRUE_FALSE} - whether the property is found - */ -extern inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE -ecma_op_object_has_property (ecma_object_t *object_p, /**< the object */ - ecma_string_t *property_name_p) /**< property name */ -{ - while (true) - { -#if JERRY_BUILTIN_PROXY - if (ECMA_OBJECT_IS_PROXY (object_p)) - { - return ecma_proxy_object_has (object_p, property_name_p); - } -#endif /* JERRY_BUILTIN_PROXY */ - - /* 2 - 3. */ - ecma_property_t property = - ecma_op_object_get_own_property (object_p, property_name_p, NULL, ECMA_PROPERTY_GET_NO_OPTIONS); - - if (property != ECMA_PROPERTY_TYPE_NOT_FOUND) - { -#if JERRY_BUILTIN_TYPEDARRAY - if (JERRY_UNLIKELY (property == ECMA_PROPERTY_TYPE_NOT_FOUND_AND_THROW)) - { - return ECMA_VALUE_ERROR; - } -#endif /* JERRY_BUILTIN_TYPEDARRAY */ - - JERRY_ASSERT (property == ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP || ECMA_PROPERTY_IS_FOUND (property)); - - return ecma_make_boolean_value (property != ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP); - } - - jmem_cpointer_t proto_cp = ecma_op_ordinary_object_get_prototype_of (object_p); - - /* 7. */ - if (proto_cp == JMEM_CP_NULL) - { - return ECMA_VALUE_FALSE; - } - - object_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, proto_cp); - } -} /* ecma_op_object_has_property */ + return has_result; +} /* ecma_op_object_find */ /** - * Search the value corresponding to a property name + * Search the value corresponding to a property index * - * Note: search includes prototypes + * Note: this method falls back to the general find method * * @return ecma value if property is found * ECMA_VALUE_NOT_FOUND if property is not found * Returned value must be freed with ecma_free_value */ ecma_value_t -ecma_op_object_find_own (ecma_value_t base_value, /**< base value */ - ecma_object_t *object_p, /**< target object */ - ecma_string_t *property_name_p) /**< property name */ +ecma_op_object_find_by_index (ecma_object_t *object_p, /**< the object */ + ecma_length_t index) /**< property index */ { - JERRY_ASSERT (object_p != NULL && !ecma_is_lexical_environment (object_p)); - JERRY_ASSERT (property_name_p != NULL); - JERRY_ASSERT (!ECMA_OBJECT_IS_PROXY (object_p)); + ecma_value_t obj_value = ecma_make_object_value (object_p); - ecma_object_base_type_t base_type = ecma_get_object_base_type (object_p); - - switch (base_type) - { - case ECMA_OBJECT_BASE_TYPE_CLASS: - { - ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; - - switch (ext_object_p->u.cls.type) - { - case ECMA_OBJECT_CLASS_STRING: - { - if (ecma_string_is_length (property_name_p)) - { - ecma_value_t prim_value_p = ext_object_p->u.cls.u3.value; - - ecma_string_t *prim_value_str_p = ecma_get_string_from_value (prim_value_p); - lit_utf8_size_t length = ecma_string_get_length (prim_value_str_p); - - return ecma_make_uint32_value (length); - } - - 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.cls.u3.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)) - { - ecma_char_t char_at_idx = ecma_string_get_char_at_pos (prim_value_str_p, index); - return ecma_make_string_value (ecma_new_ecma_string_from_code_unit (char_at_idx)); - } - } - break; - } - case ECMA_OBJECT_CLASS_ARGUMENTS: - { - if (!(ext_object_p->u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED)) - { - break; - } - - uint32_t index = ecma_string_get_array_index (property_name_p); - - if (index < ext_object_p->u.cls.u2.formal_params_number) - { - ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) ext_object_p; - - ecma_value_t *argv_p = (ecma_value_t *) (mapped_arguments_p + 1); - - if (!ecma_is_value_empty (argv_p[index]) && argv_p[index] != ECMA_VALUE_ARGUMENT_NO_TRACK) - { - ecma_string_t *name_p = ecma_op_arguments_object_get_formal_parameter (mapped_arguments_p, index); - ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, mapped_arguments_p->lex_env); - - return ecma_op_get_binding_value (lex_env_p, name_p, true); - } - } - break; - } -#if JERRY_BUILTIN_TYPEDARRAY - /* ES2015 9.4.5.4 */ - case ECMA_OBJECT_CLASS_TYPEDARRAY: - { - if (ecma_prop_name_is_symbol (property_name_p)) - { - break; - } - - uint32_t index = ecma_string_get_array_index (property_name_p); - - if (index == ECMA_STRING_NOT_ARRAY_INDEX) - { - JERRY_ASSERT (index == UINT32_MAX); - - if (!ecma_typedarray_is_element_index (property_name_p)) - { - break; - } - } - - ecma_typedarray_info_t info = ecma_typedarray_get_info (object_p); - return ecma_get_typedarray_element (&info, index); - } -#endif /* JERRY_BUILTIN_TYPEDARRAY */ -#if JERRY_MODULE_SYSTEM - case ECMA_OBJECT_CLASS_MODULE_NAMESPACE: - { - if (JERRY_UNLIKELY (ecma_prop_name_is_symbol (property_name_p))) - { - /* ECMA-262 v11, 26.3.1 */ - if (ecma_op_compare_string_to_global_symbol (property_name_p, LIT_GLOBAL_SYMBOL_TO_STRING_TAG)) - { - return ecma_make_magic_string_value (LIT_MAGIC_STRING_MODULE_UL); - } - - return ECMA_VALUE_NOT_FOUND; - } - - ecma_property_t *property_p = ecma_find_named_property (object_p, property_name_p); - - if (property_p == NULL) - { - return ECMA_VALUE_NOT_FOUND; - } - - JERRY_ASSERT (ECMA_PROPERTY_IS_RAW (*property_p)); - - ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); - - if (!(*property_p & ECMA_PROPERTY_FLAG_DATA)) - { - prop_value_p = ecma_get_property_value_from_named_reference (prop_value_p); - - if (JERRY_UNLIKELY (prop_value_p->value == ECMA_VALUE_UNINITIALIZED)) - { - return ecma_raise_reference_error (ECMA_ERR_LET_CONST_NOT_INITIALIZED); - } - } - - return ecma_fast_copy_value (prop_value_p->value); - } -#endif /* JERRY_MODULE_SYSTEM */ - } - break; - } - case ECMA_OBJECT_BASE_TYPE_ARRAY: - { - ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; - - if (ecma_string_is_length (property_name_p)) - { - return ecma_make_uint32_value (ext_object_p->u.array.length); - } - - if (JERRY_LIKELY (ecma_op_array_is_fast_array (ext_object_p))) - { - uint32_t index = ecma_string_get_array_index (property_name_p); - - if (JERRY_LIKELY (index != ECMA_STRING_NOT_ARRAY_INDEX)) - { - if (JERRY_LIKELY (index < ext_object_p->u.array.length)) - { - ecma_value_t *values_p = ECMA_GET_NON_NULL_POINTER (ecma_value_t, object_p->u1.property_list_cp); - - return (ecma_is_value_array_hole (values_p[index]) ? ECMA_VALUE_NOT_FOUND - : ecma_fast_copy_value (values_p[index])); - } - } - return ECMA_VALUE_NOT_FOUND; - } - - break; - } - default: - { - break; - } - } - - ecma_property_t *property_p = ecma_find_named_property (object_p, property_name_p); - - if (property_p == NULL) - { - switch (ecma_get_object_type (object_p)) - { - case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION: - { - if (ecma_builtin_function_is_routine (object_p)) - { - property_p = ecma_builtin_routine_try_to_instantiate_property (object_p, property_name_p); - break; - } - /* FALLTHRU */ - } - case ECMA_OBJECT_TYPE_BUILT_IN_GENERAL: - case ECMA_OBJECT_TYPE_BUILT_IN_CLASS: - case ECMA_OBJECT_TYPE_BUILT_IN_ARRAY: - { - property_p = ecma_builtin_try_to_instantiate_property (object_p, property_name_p); - break; - } - case ECMA_OBJECT_TYPE_CLASS: - { - if (((ecma_extended_object_t *) object_p)->u.cls.type == ECMA_OBJECT_CLASS_ARGUMENTS) - { - property_p = ecma_op_arguments_object_try_to_lazy_instantiate_property (object_p, property_name_p); - } - break; - } - case ECMA_OBJECT_TYPE_FUNCTION: - { -#if !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 /* !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; - } - default: - { - break; - } - } - - if (property_p == NULL) - { - return ECMA_VALUE_NOT_FOUND; - } - } - - JERRY_ASSERT (ECMA_PROPERTY_IS_RAW (*property_p)); - - ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p); - - if (*property_p & ECMA_PROPERTY_FLAG_DATA) - { - return ecma_fast_copy_value (prop_value_p->value); - } - - ecma_getter_setter_pointers_t *get_set_pair_p = ecma_get_named_accessor_property (prop_value_p); - - if (get_set_pair_p->getter_cp == JMEM_CP_NULL) - { - return ECMA_VALUE_UNDEFINED; - } - - ecma_object_t *getter_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, get_set_pair_p->getter_cp); - - return ecma_op_function_call (getter_p, base_value, NULL, 0); -} /* ecma_op_object_find_own */ - -/** - * Search the value corresponding to a property index - * - * Note: this method falls back to the general ecma_op_object_find - * - * @return ecma value if property is found - * ECMA_VALUE_NOT_FOUND if property is not found - * Returned value must be freed with ecma_free_value - */ -ecma_value_t -ecma_op_object_find_by_index (ecma_object_t *object_p, /**< the object */ - ecma_length_t index) /**< property index */ -{ if (JERRY_LIKELY (index <= ECMA_DIRECT_STRING_MAX_IMM)) { - return ecma_op_object_find (object_p, ECMA_CREATE_DIRECT_UINT32_STRING (index)); + return ecma_op_object_find (object_p, ECMA_CREATE_DIRECT_UINT32_STRING (index), obj_value); } ecma_string_t *index_str_p = ecma_new_ecma_string_from_length (index); - ecma_value_t ret_value = ecma_op_object_find (object_p, index_str_p); + ecma_value_t ret_value = ecma_op_object_find (object_p, index_str_p, obj_value); ecma_deref_ecma_string (index_str_p); return ret_value; } /* ecma_op_object_find_by_index */ -/** - * Search the value corresponding to a property name - * - * Note: search includes prototypes - * - * @return ecma value if property is found - * ECMA_VALUE_NOT_FOUND if property is not found - * Returned value must be freed with ecma_free_value - */ -ecma_value_t -ecma_op_object_find (ecma_object_t *object_p, /**< the object */ - ecma_string_t *property_name_p) /**< property name */ -{ - ecma_value_t base_value = ecma_make_object_value (object_p); - - while (true) - { -#if JERRY_BUILTIN_PROXY - if (ECMA_OBJECT_IS_PROXY (object_p)) - { - return ecma_proxy_object_find (object_p, property_name_p); - } -#endif /* JERRY_BUILTIN_PROXY */ - - ecma_value_t value = ecma_op_object_find_own (base_value, object_p, property_name_p); - - if (ecma_is_value_found (value)) - { - return value; - } - - if (object_p->u2.prototype_cp == JMEM_CP_NULL) - { - break; - } - - object_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, object_p->u2.prototype_cp); - } - - return ECMA_VALUE_NOT_FOUND; -} /* ecma_op_object_find */ - -/** - * [[Get]] operation of ecma object - * - * This function returns the value of a named property, or undefined - * if the property is not found in the prototype chain. If the property - * is an accessor, it calls the "get" callback function and returns - * with its result (including error throws). - * - * See also: - * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 - * - * @return ecma value - * Returned value must be freed with ecma_free_value - */ -extern inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE -ecma_op_object_get (ecma_object_t *object_p, /**< the object */ - ecma_string_t *property_name_p) /**< property name */ -{ - return ecma_op_object_get_with_receiver (object_p, property_name_p, ecma_make_object_value (object_p)); -} /* ecma_op_object_get */ - -/** - * [[Get]] operation of ecma object with the specified receiver - * - * This function returns the value of a named property, or undefined - * if the property is not found in the prototype chain. If the property - * is an accessor, it calls the "get" callback function and returns - * with its result (including error throws). - * - * See also: - * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 - * - * @return ecma value - * Returned value must be freed with ecma_free_value - */ -ecma_value_t -ecma_op_object_get_with_receiver (ecma_object_t *object_p, /**< the object */ - ecma_string_t *property_name_p, /**< property name */ - ecma_value_t receiver) /**< receiver to invoke getter function */ -{ - while (true) - { -#if JERRY_BUILTIN_PROXY - if (ECMA_OBJECT_IS_PROXY (object_p)) - { - return ecma_proxy_object_get (object_p, property_name_p, receiver); - } -#endif /* JERRY_BUILTIN_PROXY */ - - ecma_value_t value = ecma_op_object_find_own (receiver, object_p, property_name_p); - - if (ecma_is_value_found (value)) - { - return value; - } - - jmem_cpointer_t proto_cp = ecma_op_ordinary_object_get_prototype_of (object_p); - - if (proto_cp == JMEM_CP_NULL) - { - break; - } - - object_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, proto_cp); - } - - return ECMA_VALUE_UNDEFINED; -} /* ecma_op_object_get_with_receiver */ - /** * [[Get]] operation of ecma object specified for property index * @@ -906,13 +399,15 @@ ecma_value_t ecma_op_object_get_by_index (ecma_object_t *object_p, /**< the object */ ecma_length_t index) /**< property index */ { + ecma_value_t obj_value = ecma_make_object_value (object_p); + if (JERRY_LIKELY (index <= ECMA_DIRECT_STRING_MAX_IMM)) { - return ecma_op_object_get (object_p, ECMA_CREATE_DIRECT_UINT32_STRING (index)); + return ecma_internal_method_get (object_p, ECMA_CREATE_DIRECT_UINT32_STRING (index), obj_value); } ecma_string_t *index_str_p = ecma_new_ecma_string_from_length (index); - ecma_value_t ret_value = ecma_op_object_get (object_p, index_str_p); + ecma_value_t ret_value = ecma_internal_method_get (object_p, index_str_p, obj_value); ecma_deref_ecma_string (index_str_p); return ret_value; @@ -963,7 +458,7 @@ extern inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE ecma_op_object_get_by_magic_id (ecma_object_t *object_p, /**< the object */ lit_magic_string_id_t property_id) /**< property magic string id */ { - return ecma_op_object_get (object_p, ecma_get_magic_string (property_id)); + return ecma_internal_method_get (object_p, ecma_get_magic_string (property_id), ecma_make_object_value (object_p)); } /* ecma_op_object_get_by_magic_id */ #if JERRY_ESNEXT @@ -1045,7 +540,7 @@ ecma_op_object_get_by_symbol_id (ecma_object_t *object_p, /**< the object */ lit_magic_string_id_t property_id) /**< property symbol id */ { ecma_string_t *symbol_p = ecma_op_get_global_symbol (property_id); - ecma_value_t ret_value = ecma_op_object_get (object_p, symbol_p); + ecma_value_t ret_value = ecma_internal_method_get (object_p, symbol_p, ecma_make_object_value (object_p)); ecma_deref_ecma_string (symbol_p); return ret_value; @@ -1075,9 +570,7 @@ ecma_op_get_method (ecma_value_t value, /**< ecma value */ } ecma_object_t *obj_p = ecma_get_object_from_value (obj_value); - ecma_value_t func; - - func = ecma_op_object_get (obj_p, prop_name_p); + ecma_value_t func = ecma_internal_method_get (obj_p, prop_name_p, obj_value); ecma_deref_object (obj_p); /* 3. */ @@ -1158,1432 +651,256 @@ ecma_op_object_put_by_index (ecma_object_t *object_p, /**< the object */ ecma_value_t value, /**< ecma value */ bool is_throw) /**< flag that controls failure handling */ { + ecma_value_t obj_value = ecma_make_object_value (object_p); + if (JERRY_LIKELY (index <= ECMA_DIRECT_STRING_MAX_IMM)) { - return ecma_op_object_put (object_p, ECMA_CREATE_DIRECT_UINT32_STRING (index), value, is_throw); + return ecma_internal_method_set (object_p, ECMA_CREATE_DIRECT_UINT32_STRING (index), value, obj_value, is_throw); } ecma_string_t *index_str_p = ecma_new_ecma_string_from_length (index); - ecma_value_t ret_value = ecma_op_object_put (object_p, index_str_p, value, is_throw); + ecma_value_t ret_value = ecma_internal_method_set (object_p, index_str_p, value, obj_value, is_throw); ecma_deref_ecma_string (index_str_p); return ret_value; } /* ecma_op_object_put_by_index */ /** - * [[Put]] ecma general object's operation - * - * See also: - * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 - * ECMA-262 v5, 8.12.5 - * Also incorporates [[CanPut]] ECMA-262 v5, 8.12.4 - * - * @return ecma value - * The returned value must be freed with ecma_free_value. + * [[Delete]] ecma object's operation specialized for property index * - * Returns with ECMA_VALUE_TRUE if the operation is - * successful. Otherwise it returns with an error object - * or ECMA_VALUE_FALSE. + * Note: + * This method falls back to the general [[Delete]] internal method * - * Note: even if is_throw is false, the setter can throw an - * error, and this function returns with that error. + * @return true - if deleted successfully + * false - or type error otherwise (based in 'is_throw') */ -extern inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE -ecma_op_object_put (ecma_object_t *object_p, /**< the object */ - ecma_string_t *property_name_p, /**< property name */ - ecma_value_t value, /**< ecma value */ - bool is_throw) /**< flag that controls failure handling */ +ecma_value_t +ecma_op_object_delete_by_index (ecma_object_t *obj_p, /**< the object */ + ecma_length_t index, /**< property index */ + bool is_throw) /**< flag that controls failure handling */ { - return ecma_op_object_put_with_receiver (object_p, - property_name_p, - value, - ecma_make_object_value (object_p), - is_throw); -} /* ecma_op_object_put */ + if (JERRY_LIKELY (index <= ECMA_DIRECT_STRING_MAX_IMM)) + { + return ecma_internal_method_delete (obj_p, ECMA_CREATE_DIRECT_UINT32_STRING (index), is_throw); + } -#if JERRY_ESNEXT -/** - * [[Set]] ( P, V, Receiver) operation part for ordinary objects + ecma_string_t *index_str_p = ecma_new_ecma_string_from_length (index); + ecma_value_t ret_value = ecma_internal_method_delete (obj_p, index_str_p, is_throw); + ecma_deref_ecma_string (index_str_p); + + return ret_value; +} /* ecma_op_object_delete_by_index */ + +/** + * [[DefaultValue]] ecma object's operation * - * See also: ECMAScript v6, 9.19.9 + * See also: + * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 * * @return ecma value - * The returned value must be freed with ecma_free_value. + * Returned value must be freed with ecma_free_value */ -static ecma_value_t -ecma_op_object_put_apply_receiver (ecma_value_t receiver, /**< receiver */ - ecma_string_t *property_name_p, /**< property name */ - ecma_value_t value, /**< value to set */ - bool is_throw) /**< flag that controls failure handling */ +ecma_value_t +ecma_op_object_default_value (ecma_object_t *obj_p, /**< the object */ + ecma_preferred_type_hint_t hint) /**< hint on preferred result type */ { - /* 5.b */ - if (!ecma_is_value_object (receiver)) - { - return ECMA_REJECT (is_throw, ECMA_ERR_RECEIVER_MUST_BE_AN_OBJECT); - } - - ecma_object_t *receiver_obj_p = ecma_get_object_from_value (receiver); - - ecma_property_descriptor_t prop_desc; - /* 5.c */ - ecma_value_t status = ecma_op_object_get_own_property_descriptor (receiver_obj_p, property_name_p, &prop_desc); - - /* 5.d */ - if (ECMA_IS_VALUE_ERROR (status)) - { - return status; - } - - /* 5.e */ - if (ecma_is_value_true (status)) - { - ecma_value_t result; - - /* 5.e.i - 5.e.ii */ - if (prop_desc.flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED) - || !(prop_desc.flags & JERRY_PROP_IS_WRITABLE)) - { - result = ecma_raise_property_redefinition (property_name_p, prop_desc.flags); - } - else - { - /* 5.e.iii */ - JERRY_ASSERT (prop_desc.flags & JERRY_PROP_IS_VALUE_DEFINED); - ecma_free_value (prop_desc.value); - prop_desc.value = ecma_copy_value (value); - - /* 5.e.iv */ - result = ecma_op_object_define_own_property (receiver_obj_p, property_name_p, &prop_desc); - - if (JERRY_UNLIKELY (ecma_is_value_false (result))) - { - result = ECMA_REJECT (is_throw, ECMA_ERR_PROXY_TRAP_RETURNED_FALSISH); - } - } - - ecma_free_property_descriptor (&prop_desc); - - return result; - } - -#if JERRY_BUILTIN_PROXY - if (ECMA_OBJECT_IS_PROXY (receiver_obj_p)) - { - ecma_property_descriptor_t desc; - /* Based on: ES6 9.1.9 [[Set]] 4.d.i. / ES11 9.1.9.2 OrdinarySetWithOwnDescriptor 2.c.i. */ - desc.flags = (JERRY_PROP_IS_CONFIGURABLE | JERRY_PROP_IS_CONFIGURABLE_DEFINED | JERRY_PROP_IS_ENUMERABLE - | JERRY_PROP_IS_ENUMERABLE_DEFINED | JERRY_PROP_IS_WRITABLE | JERRY_PROP_IS_WRITABLE_DEFINED - | JERRY_PROP_IS_VALUE_DEFINED); - desc.value = value; - ecma_value_t ret_value = ecma_proxy_object_define_own_property (receiver_obj_p, property_name_p, &desc); - - if (JERRY_UNLIKELY (ecma_is_value_false (ret_value))) - { - ret_value = ECMA_REJECT (is_throw, ECMA_ERR_PROXY_TRAP_RETURNED_FALSISH); - } + JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p)); - return ret_value; - } -#endif /* JERRY_BUILTIN_PROXY */ + JERRY_ASSERT_OBJECT_TYPE_IS_VALID (ecma_get_object_type (obj_p)); - if (JERRY_UNLIKELY (ecma_op_object_is_fast_array (receiver_obj_p))) - { - ecma_fast_array_convert_to_normal (receiver_obj_p); - } + /* + * typedef ecma_property_t * (*default_value_ptr_t) (ecma_object_t *, ecma_string_t *); + * static const default_value_ptr_t default_value [ECMA_OBJECT_TYPE__COUNT] = + * { + * [ECMA_OBJECT_TYPE_GENERAL] = &ecma_op_general_object_default_value, + * [ECMA_OBJECT_TYPE_CLASS] = &ecma_op_general_object_default_value, + * [ECMA_OBJECT_TYPE_FUNCTION] = &ecma_op_general_object_default_value, + * [ECMA_OBJECT_TYPE_NATIVE_FUNCTION] = &ecma_op_general_object_default_value, + * [ECMA_OBJECT_TYPE_ARRAY] = &ecma_op_general_object_default_value, + * [ECMA_OBJECT_TYPE_BOUND_FUNCTION] = &ecma_op_general_object_default_value, + * [ECMA_OBJECT_TYPE_PSEUDO_ARRAY] = &ecma_op_general_object_default_value + * }; + * + * return default_value[type] (obj_p, property_name_p); + */ - /* 5.f.i */ - ecma_property_value_t *new_prop_value_p; - new_prop_value_p = ecma_create_named_data_property (receiver_obj_p, - property_name_p, - ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, - NULL); - JERRY_ASSERT (ecma_is_value_undefined (new_prop_value_p->value)); - new_prop_value_p->value = ecma_copy_value_if_not_object (value); - - return ECMA_VALUE_TRUE; -} /* ecma_op_object_put_apply_receiver */ -#endif /* JERRY_ESNEXT */ + return ecma_op_general_object_default_value (obj_p, hint); +} /* ecma_op_object_default_value */ /** - * [[Put]] ecma general object's operation with given receiver + * [[HasInstance]] ecma object's operation * * See also: - * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 - * ECMA-262 v5, 8.12.5 - * ECMA-262 v6, 9.1.9 - * Also incorporates [[CanPut]] ECMA-262 v5, 8.12.4 - * - * @return ecma value - * The returned value must be freed with ecma_free_value. - * - * Returns with ECMA_VALUE_TRUE if the operation is - * successful. Otherwise it returns with an error object - * or ECMA_VALUE_FALSE. + * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 9 * - * Note: even if is_throw is false, the setter can throw an - * error, and this function returns with that error. + * @return ecma value containing a boolean value or an error + * Returned value must be freed with ecma_free_value */ ecma_value_t -ecma_op_object_put_with_receiver (ecma_object_t *object_p, /**< the object */ - ecma_string_t *property_name_p, /**< property name */ - ecma_value_t value, /**< ecma value */ - ecma_value_t receiver, /**< receiver */ - bool is_throw) /**< flag that controls failure handling */ +ecma_op_object_has_instance (ecma_object_t *obj_p, /**< the object */ + ecma_value_t value) /**< argument 'V' */ { - JERRY_ASSERT (object_p != NULL && !ecma_is_lexical_environment (object_p)); - JERRY_ASSERT (property_name_p != NULL); - -#if JERRY_BUILTIN_PROXY - if (ECMA_OBJECT_IS_PROXY (object_p)) - { - return ecma_proxy_object_set (object_p, property_name_p, value, receiver, is_throw); - } -#endif /* JERRY_BUILTIN_PROXY */ + JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p)); - ecma_object_base_type_t base_type = ecma_get_object_base_type (object_p); + JERRY_ASSERT_OBJECT_TYPE_IS_VALID (ecma_get_object_type (obj_p)); - switch (base_type) + if (ecma_op_object_is_callable (obj_p)) { - case ECMA_OBJECT_BASE_TYPE_CLASS: - { - ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; - - switch (ext_object_p->u.cls.type) - { - case ECMA_OBJECT_CLASS_ARGUMENTS: - { - if (!(ext_object_p->u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED)) - { - break; - } - - uint32_t index = ecma_string_get_array_index (property_name_p); - - if (index < ext_object_p->u.cls.u2.formal_params_number) - { - ecma_mapped_arguments_t *mapped_arguments_p = (ecma_mapped_arguments_t *) ext_object_p; - - ecma_value_t *argv_p = (ecma_value_t *) (mapped_arguments_p + 1); - - if (!ecma_is_value_empty (argv_p[index]) && argv_p[index] != ECMA_VALUE_ARGUMENT_NO_TRACK) - { - ecma_string_t *name_p = ecma_op_arguments_object_get_formal_parameter (mapped_arguments_p, index); - ecma_object_t *lex_env_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_object_t, mapped_arguments_p->lex_env); - ecma_op_set_mutable_binding (lex_env_p, name_p, value, true); - return ECMA_VALUE_TRUE; - } - } - break; - } -#if JERRY_BUILTIN_TYPEDARRAY - /* ES2015 9.4.5.5 */ - case ECMA_OBJECT_CLASS_TYPEDARRAY: - { - if (ecma_prop_name_is_symbol (property_name_p)) - { - break; - } - - uint32_t index = ecma_string_get_array_index (property_name_p); - - if (index == ECMA_STRING_NOT_ARRAY_INDEX) - { - JERRY_ASSERT (index == UINT32_MAX); - - if (!ecma_typedarray_is_element_index (property_name_p)) - { - break; - } - } - - ecma_typedarray_info_t info = ecma_typedarray_get_info (object_p); - return ecma_set_typedarray_element (&info, value, index); - } -#endif /* JERRY_BUILTIN_TYPEDARRAY */ -#if JERRY_MODULE_SYSTEM - case ECMA_OBJECT_CLASS_MODULE_NAMESPACE: - { - return ecma_raise_readonly_assignment (property_name_p, is_throw); - } -#endif /* JERRY_MODULE_SYSTEM */ - } - break; - } - case ECMA_OBJECT_BASE_TYPE_ARRAY: - { - ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; - - if (ecma_string_is_length (property_name_p)) - { - if (ecma_is_property_writable ((ecma_property_t) ext_object_p->u.array.length_prop_and_hole_count)) - { - return ecma_op_array_object_set_length (object_p, value, 0); - } - - return ecma_raise_readonly_assignment (property_name_p, is_throw); - } - - if (JERRY_LIKELY (ecma_op_array_is_fast_array (ext_object_p))) - { - uint32_t index = ecma_string_get_array_index (property_name_p); - - if (JERRY_UNLIKELY (index == ECMA_STRING_NOT_ARRAY_INDEX)) - { - ecma_fast_array_convert_to_normal (object_p); - } - else if (ecma_fast_array_set_property (object_p, index, value)) - { - return ECMA_VALUE_TRUE; - } - } - - JERRY_ASSERT (!ecma_op_object_is_fast_array (object_p)); - break; - } - default: - { - break; - } + return ecma_op_function_has_instance (obj_p, value); } - ecma_property_t *property_p = ecma_find_named_property (object_p, property_name_p); - - if (property_p == NULL) - { - switch (ecma_get_object_type (object_p)) - { - case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION: - { - if (ecma_builtin_function_is_routine (object_p)) - { - property_p = ecma_builtin_routine_try_to_instantiate_property (object_p, property_name_p); - break; - } - /* FALLTHRU */ - } - case ECMA_OBJECT_TYPE_BUILT_IN_GENERAL: - case ECMA_OBJECT_TYPE_BUILT_IN_CLASS: - case ECMA_OBJECT_TYPE_BUILT_IN_ARRAY: - { - property_p = ecma_builtin_try_to_instantiate_property (object_p, property_name_p); - break; - } - case ECMA_OBJECT_TYPE_CLASS: - { - ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; - - switch (ext_object_p->u.cls.type) - { - case ECMA_OBJECT_CLASS_STRING: - { - 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.cls.u3.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_raise_readonly_assignment (property_name_p, is_throw); - } - } - break; - } - case ECMA_OBJECT_CLASS_ARGUMENTS: - { - property_p = ecma_op_arguments_object_try_to_lazy_instantiate_property (object_p, property_name_p); - break; - } - } - break; - } - case ECMA_OBJECT_TYPE_FUNCTION: - { - if (ecma_string_is_length (property_name_p)) - { - /* Uninitialized 'length' property is non-writable (ECMA-262 v6, 19.2.4.1) */ -#if JERRY_ESNEXT - if (!ECMA_GET_FIRST_BIT_FROM_POINTER_TAG (((ecma_extended_object_t *) object_p)->u.function.scope_cp)) -#endif /* JERRY_ESNEXT */ - { - return ecma_raise_readonly_assignment (property_name_p, is_throw); - } - } - - /* 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; - } - default: - { - break; - } - } - } + return ecma_raise_type_error (ECMA_ERR_EXPECTED_A_FUNCTION_OBJECT); +} /* ecma_op_object_has_instance */ - jmem_cpointer_t setter_cp = JMEM_CP_NULL; +/** + * Object's isPrototypeOf operation + * + * See also: + * ECMA-262 v5, 15.2.4.6; 3 + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_TRUE - if the target object is prototype of the base object + * ECMA_VALUE_FALSE - if the target object is not prototype of the base object + */ +ecma_value_t +ecma_op_object_is_prototype_of (ecma_object_t *base_p, /**< base object */ + ecma_object_t *target_p) /**< target object */ +{ + ecma_ref_object (target_p); - if (property_p != NULL) + do { - JERRY_ASSERT (ECMA_PROPERTY_IS_RAW (*property_p)); - - if (*property_p & ECMA_PROPERTY_FLAG_DATA) - { - if (ecma_is_property_writable (*property_p)) - { -#if JERRY_ESNEXT - if (ecma_make_object_value (object_p) != receiver) - { - return ecma_op_object_put_apply_receiver (receiver, property_name_p, value, is_throw); - } -#endif /* JERRY_ESNEXT */ + ecma_object_t *proto_p = ecma_internal_method_get_prototype_of (target_p); + ecma_deref_object (target_p); - /* There is no need for special casing arrays here because changing the - * value of an existing property never changes the length of an array. */ - ecma_named_data_property_assign_value (object_p, ECMA_PROPERTY_VALUE_PTR (property_p), value); - return ECMA_VALUE_TRUE; - } - } - else + if (proto_p == NULL) { - ecma_getter_setter_pointers_t *get_set_pair_p; - get_set_pair_p = ecma_get_named_accessor_property (ECMA_PROPERTY_VALUE_PTR (property_p)); - setter_cp = get_set_pair_p->setter_cp; + return ECMA_VALUE_FALSE; } - } - else - { - bool create_new_property = true; - - jmem_cpointer_t obj_cp; - ECMA_SET_NON_NULL_POINTER (obj_cp, object_p); - ecma_object_t *proto_p = object_p; - - while (true) + else if (proto_p == ECMA_OBJECT_POINTER_ERROR) { - obj_cp = ecma_op_ordinary_object_get_prototype_of (proto_p); - - if (obj_cp == JMEM_CP_NULL) - { - break; - } - - ecma_property_ref_t property_ref = { NULL }; - proto_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, obj_cp); - -#if JERRY_BUILTIN_PROXY - if (ECMA_OBJECT_IS_PROXY (proto_p)) - { - return ecma_op_object_put_with_receiver (proto_p, property_name_p, value, receiver, is_throw); - } -#endif /* JERRY_BUILTIN_PROXY */ - - ecma_property_t inherited_property = - ecma_op_object_get_own_property (proto_p, property_name_p, &property_ref, ECMA_PROPERTY_GET_NO_OPTIONS); - - if (ECMA_PROPERTY_IS_FOUND (inherited_property)) - { - JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (inherited_property)); - - if (!(inherited_property & ECMA_PROPERTY_FLAG_DATA)) - { - setter_cp = ecma_get_named_accessor_property (property_ref.value_p)->setter_cp; - create_new_property = false; - break; - } - - create_new_property = ecma_is_property_writable (inherited_property); - break; - } - - JERRY_ASSERT (inherited_property == ECMA_PROPERTY_TYPE_NOT_FOUND - || inherited_property == ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP); + return ECMA_VALUE_ERROR; } - -#if JERRY_BUILTIN_PROXY - if (create_new_property && ecma_is_value_object (receiver) - && ECMA_OBJECT_IS_PROXY (ecma_get_object_from_value (receiver))) + else if (proto_p == base_p) { - return ecma_op_object_put_apply_receiver (receiver, property_name_p, value, is_throw); + ecma_deref_object (proto_p); + return ECMA_VALUE_TRUE; } -#endif /* JERRY_BUILTIN_PROXY */ - - if (create_new_property && ecma_op_ordinary_object_is_extensible (object_p)) - { - const ecma_object_base_type_t obj_base_type = ecma_get_object_base_type (object_p); - - if (obj_base_type == ECMA_OBJECT_BASE_TYPE_CLASS) - { - ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; - - if (ext_object_p->u.cls.type == ECMA_OBJECT_CLASS_ARGUMENTS - && ext_object_p->u.cls.u1.arguments_flags & ECMA_ARGUMENTS_OBJECT_MAPPED) - { - const uint32_t flags = ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE | JERRY_PROP_SHOULD_THROW; - return ecma_builtin_helper_def_prop (object_p, property_name_p, value, flags); - } - } - - uint32_t index = ecma_string_get_array_index (property_name_p); - - if (obj_base_type == ECMA_OBJECT_BASE_TYPE_ARRAY && index != ECMA_STRING_NOT_ARRAY_INDEX) - { - ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p; - - if (index < UINT32_MAX && index >= ext_object_p->u.array.length) - { - if (!ecma_is_property_writable ((ecma_property_t) ext_object_p->u.array.length_prop_and_hole_count)) - { - return ecma_raise_readonly_assignment (property_name_p, is_throw); - } - - ext_object_p->u.array.length = index + 1; - } - } - -#if JERRY_ESNEXT - return ecma_op_object_put_apply_receiver (receiver, property_name_p, value, is_throw); -#endif /* JERRY_ESNEXT */ - - ecma_property_value_t *new_prop_value_p; - new_prop_value_p = ecma_create_named_data_property (object_p, - property_name_p, - ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, - NULL); - - JERRY_ASSERT (ecma_is_value_undefined (new_prop_value_p->value)); - new_prop_value_p->value = ecma_copy_value_if_not_object (value); - return ECMA_VALUE_TRUE; - } - } - - if (setter_cp == JMEM_CP_NULL) - { - return ecma_raise_readonly_assignment (property_name_p, is_throw); - } - - ecma_value_t ret_value = - ecma_op_function_call (ECMA_GET_NON_NULL_POINTER (ecma_object_t, setter_cp), receiver, &value, 1); - - if (!ECMA_IS_VALUE_ERROR (ret_value)) - { - ecma_fast_free_value (ret_value); - ret_value = ECMA_VALUE_TRUE; - } - - return ret_value; -} /* ecma_op_object_put_with_receiver */ - -/** - * [[Delete]] ecma object's operation specialized for property index - * - * Note: - * This method falls back to the general ecma_op_object_delete - * - * @return true - if deleted successfully - * false - or type error otherwise (based in 'is_throw') - */ -ecma_value_t -ecma_op_object_delete_by_index (ecma_object_t *obj_p, /**< the object */ - ecma_length_t index, /**< property index */ - bool is_throw) /**< flag that controls failure handling */ -{ - if (JERRY_LIKELY (index <= ECMA_DIRECT_STRING_MAX_IMM)) - { - return ecma_op_object_delete (obj_p, ECMA_CREATE_DIRECT_UINT32_STRING (index), is_throw); - ; - } - - ecma_string_t *index_str_p = ecma_new_ecma_string_from_length (index); - ecma_value_t ret_value = ecma_op_object_delete (obj_p, index_str_p, is_throw); - ecma_deref_ecma_string (index_str_p); - - return ret_value; -} /* ecma_op_object_delete_by_index */ - -/** - * [[Delete]] ecma object's operation - * - * See also: - * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 - * - * Note: - * returned value must be freed with ecma_free_value - * - * @return true - if deleted successfully - * false - or type error otherwise (based in 'is_throw') - */ -ecma_value_t -ecma_op_object_delete (ecma_object_t *obj_p, /**< the object */ - ecma_string_t *property_name_p, /**< property name */ - bool is_strict) /**< flag that controls failure handling */ -{ - JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p)); - JERRY_ASSERT (property_name_p != NULL); - -#if JERRY_BUILTIN_PROXY - if (ECMA_OBJECT_IS_PROXY (obj_p)) - { - return ecma_proxy_object_delete_property (obj_p, property_name_p, is_strict); - } -#endif /* JERRY_BUILTIN_PROXY */ - - JERRY_ASSERT_OBJECT_TYPE_IS_VALID (ecma_get_object_type (obj_p)); - - return ecma_op_general_object_delete (obj_p, property_name_p, is_strict); -} /* ecma_op_object_delete */ - -/** - * [[DefaultValue]] ecma object's operation - * - * See also: - * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 - * - * @return ecma value - * Returned value must be freed with ecma_free_value - */ -ecma_value_t -ecma_op_object_default_value (ecma_object_t *obj_p, /**< the object */ - ecma_preferred_type_hint_t hint) /**< hint on preferred result type */ -{ - JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p)); - - JERRY_ASSERT_OBJECT_TYPE_IS_VALID (ecma_get_object_type (obj_p)); - - /* - * typedef ecma_property_t * (*default_value_ptr_t) (ecma_object_t *, ecma_string_t *); - * static const default_value_ptr_t default_value [ECMA_OBJECT_TYPE__COUNT] = - * { - * [ECMA_OBJECT_TYPE_GENERAL] = &ecma_op_general_object_default_value, - * [ECMA_OBJECT_TYPE_CLASS] = &ecma_op_general_object_default_value, - * [ECMA_OBJECT_TYPE_FUNCTION] = &ecma_op_general_object_default_value, - * [ECMA_OBJECT_TYPE_NATIVE_FUNCTION] = &ecma_op_general_object_default_value, - * [ECMA_OBJECT_TYPE_ARRAY] = &ecma_op_general_object_default_value, - * [ECMA_OBJECT_TYPE_BOUND_FUNCTION] = &ecma_op_general_object_default_value, - * [ECMA_OBJECT_TYPE_PSEUDO_ARRAY] = &ecma_op_general_object_default_value - * }; - * - * return default_value[type] (obj_p, property_name_p); - */ - - return ecma_op_general_object_default_value (obj_p, hint); -} /* ecma_op_object_default_value */ - -/** - * [[DefineOwnProperty]] ecma object's operation - * - * See also: - * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 - * - * @return ecma value - * Returned value must be freed with ecma_free_value - */ -ecma_value_t -ecma_op_object_define_own_property (ecma_object_t *obj_p, /**< the object */ - ecma_string_t *property_name_p, /**< property name */ - const ecma_property_descriptor_t *property_desc_p) /**< property - * descriptor */ -{ - JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p)); - JERRY_ASSERT (property_name_p != NULL); - - const ecma_object_type_t type = ecma_get_object_type (obj_p); - - switch (type) - { - case ECMA_OBJECT_TYPE_CLASS: - { - ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; - - switch (ext_object_p->u.cls.type) - { - case ECMA_OBJECT_CLASS_ARGUMENTS: - { - return ecma_op_arguments_object_define_own_property (obj_p, property_name_p, property_desc_p); - } -#if JERRY_BUILTIN_TYPEDARRAY - /* ES2015 9.4.5.1 */ - case ECMA_OBJECT_CLASS_TYPEDARRAY: - { - return ecma_op_typedarray_define_own_property (obj_p, property_name_p, property_desc_p); - } -#endif /* JERRY_BUILTIN_TYPEDARRAY */ - } - break; - } - case ECMA_OBJECT_TYPE_ARRAY: - case ECMA_OBJECT_TYPE_BUILT_IN_ARRAY: - { - return ecma_op_array_object_define_own_property (obj_p, property_name_p, property_desc_p); - } -#if JERRY_BUILTIN_PROXY - case ECMA_OBJECT_TYPE_PROXY: - { - return ecma_proxy_object_define_own_property (obj_p, property_name_p, property_desc_p); - } -#endif /* JERRY_BUILTIN_PROXY */ - default: - { - break; - } - } - - return ecma_op_general_object_define_own_property (obj_p, property_name_p, property_desc_p); -} /* ecma_op_object_define_own_property */ - -/** - * Get property descriptor from specified property - * - * depending on the property type the following fields are set: - * - for named data properties: { [Value], [Writable], [Enumerable], [Configurable] }; - * - for named accessor properties: { [Get] - if defined, - * [Set] - if defined, - * [Enumerable], [Configurable] - * }. - * - * The output property descriptor will always be initialized to an empty descriptor. - * - * @return ECMA_VALUE_ERROR - if the Proxy.[[GetOwnProperty]] operation raises error - * ECMA_VALUE_{TRUE, FALSE} - if property found or not - */ -ecma_value_t -ecma_op_object_get_own_property_descriptor (ecma_object_t *object_p, /**< the object */ - ecma_string_t *property_name_p, /**< property name */ - ecma_property_descriptor_t *prop_desc_p) /**< property descriptor */ -{ - *prop_desc_p = ecma_make_empty_property_descriptor (); - -#if JERRY_BUILTIN_PROXY - if (ECMA_OBJECT_IS_PROXY (object_p)) - { - return ecma_proxy_object_get_own_property_descriptor (object_p, property_name_p, prop_desc_p); - } -#endif /* JERRY_BUILTIN_PROXY */ - - ecma_property_ref_t property_ref; - property_ref.virtual_value = ECMA_VALUE_EMPTY; - ecma_property_t property = - ecma_op_object_get_own_property (object_p, property_name_p, &property_ref, ECMA_PROPERTY_GET_VALUE); - - if (!ECMA_PROPERTY_IS_FOUND (property)) - { -#if JERRY_BUILTIN_TYPEDARRAY - if (JERRY_UNLIKELY (property == ECMA_PROPERTY_TYPE_NOT_FOUND_AND_THROW)) - { - return ECMA_VALUE_ERROR; - } -#endif /* JERRY_BUILTIN_TYPEDARRAY */ - - JERRY_ASSERT (property == ECMA_PROPERTY_TYPE_NOT_FOUND || property == ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP); - - return ECMA_VALUE_FALSE; - } - - uint32_t flags = ecma_is_property_enumerable (property) ? JERRY_PROP_IS_ENUMERABLE : JERRY_PROP_NO_OPTS; - flags |= ecma_is_property_configurable (property) ? JERRY_PROP_IS_CONFIGURABLE : JERRY_PROP_NO_OPTS; - - prop_desc_p->flags = (uint16_t) (JERRY_PROP_IS_ENUMERABLE_DEFINED | JERRY_PROP_IS_CONFIGURABLE_DEFINED | flags); - - if (property & ECMA_PROPERTY_FLAG_DATA) - { - if (!ECMA_PROPERTY_IS_VIRTUAL (property)) - { - prop_desc_p->value = ecma_copy_value (property_ref.value_p->value); - } - else - { -#if JERRY_MODULE_SYSTEM - if (JERRY_UNLIKELY (property_ref.virtual_value == ECMA_VALUE_UNINITIALIZED)) - { - return ecma_raise_reference_error (ECMA_ERR_LET_CONST_NOT_INITIALIZED); - } -#endif /* JERRY_MODULE_SYSTEM */ - prop_desc_p->value = property_ref.virtual_value; - } - - prop_desc_p->flags |= (JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_WRITABLE_DEFINED); - prop_desc_p->flags = (uint16_t) ( - prop_desc_p->flags | (ecma_is_property_writable (property) ? JERRY_PROP_IS_WRITABLE : JERRY_PROP_NO_OPTS)); - } - else - { - ecma_getter_setter_pointers_t *get_set_pair_p = ecma_get_named_accessor_property (property_ref.value_p); - prop_desc_p->flags |= (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED); - - if (get_set_pair_p->getter_cp == JMEM_CP_NULL) - { - prop_desc_p->get_p = NULL; - } - else - { - prop_desc_p->get_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, get_set_pair_p->getter_cp); - ecma_ref_object (prop_desc_p->get_p); - } - - if (get_set_pair_p->setter_cp == JMEM_CP_NULL) - { - prop_desc_p->set_p = NULL; - } - else - { - prop_desc_p->set_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, get_set_pair_p->setter_cp); - ecma_ref_object (prop_desc_p->set_p); - } - } - - return ECMA_VALUE_TRUE; -} /* ecma_op_object_get_own_property_descriptor */ - -#if JERRY_BUILTIN_PROXY -/** - * Get property descriptor from a target value for a specified property. - * - * For more details see ecma_op_object_get_own_property_descriptor - * - * @return ECMA_VALUE_ERROR - if the Proxy.[[GetOwnProperty]] operation raises error - * ECMA_VALUE_{TRUE, FALSE} - if property found or not - */ -ecma_value_t -ecma_op_get_own_property_descriptor (ecma_value_t target, /**< target value */ - ecma_string_t *property_name_p, /**< property name */ - ecma_property_descriptor_t *prop_desc_p) /**< property descriptor */ -{ - if (!ecma_is_value_object (target)) - { - return ECMA_VALUE_FALSE; - } - - return ecma_op_object_get_own_property_descriptor (ecma_get_object_from_value (target), property_name_p, prop_desc_p); -} /* ecma_op_get_own_property_descriptor */ -#endif /* JERRY_BUILTIN_PROXY */ - -/** - * [[HasInstance]] ecma object's operation - * - * See also: - * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 9 - * - * @return ecma value containing a boolean value or an error - * Returned value must be freed with ecma_free_value - */ -ecma_value_t -ecma_op_object_has_instance (ecma_object_t *obj_p, /**< the object */ - ecma_value_t value) /**< argument 'V' */ -{ - JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p)); - - JERRY_ASSERT_OBJECT_TYPE_IS_VALID (ecma_get_object_type (obj_p)); - - if (ecma_op_object_is_callable (obj_p)) - { - return ecma_op_function_has_instance (obj_p, value); - } - - return ecma_raise_type_error (ECMA_ERR_EXPECTED_A_FUNCTION_OBJECT); -} /* ecma_op_object_has_instance */ - -/** - * General [[GetPrototypeOf]] abstract operation - * - * Note: returned valid object must be freed. - * - * @return ecma_object_t * - prototype of the input object. - * ECMA_OBJECT_POINTER_ERROR - error reported during Proxy resolve. - * NULL - the input object does not have a prototype. - */ -ecma_object_t * -ecma_op_object_get_prototype_of (ecma_object_t *obj_p) /**< input object */ -{ - JERRY_ASSERT (obj_p != NULL); - -#if JERRY_BUILTIN_PROXY - if (ECMA_OBJECT_IS_PROXY (obj_p)) - { - ecma_value_t proto = ecma_proxy_object_get_prototype_of (obj_p); - - if (ECMA_IS_VALUE_ERROR (proto)) - { - return ECMA_OBJECT_POINTER_ERROR; - } - if (ecma_is_value_null (proto)) - { - return NULL; - } - - JERRY_ASSERT (ecma_is_value_object (proto)); - - return ecma_get_object_from_value (proto); - } - else -#endif /* JERRY_BUILTIN_PROXY */ - { - jmem_cpointer_t proto_cp = ecma_op_ordinary_object_get_prototype_of (obj_p); - - if (proto_cp == JMEM_CP_NULL) - { - return NULL; - } - - ecma_object_t *proto_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, proto_cp); - ecma_ref_object (proto_p); - - return proto_p; - } -} /* ecma_op_object_get_prototype_of */ - -/** - * Object's isPrototypeOf operation - * - * See also: - * ECMA-262 v5, 15.2.4.6; 3 - * - * @return ECMA_VALUE_ERROR - if the operation fails - * ECMA_VALUE_TRUE - if the target object is prototype of the base object - * ECMA_VALUE_FALSE - if the target object is not prototype of the base object - */ -ecma_value_t -ecma_op_object_is_prototype_of (ecma_object_t *base_p, /**< base object */ - ecma_object_t *target_p) /**< target object */ -{ - ecma_ref_object (target_p); - - do - { - ecma_object_t *proto_p = ecma_op_object_get_prototype_of (target_p); - ecma_deref_object (target_p); - - if (proto_p == NULL) - { - return ECMA_VALUE_FALSE; - } - else if (proto_p == ECMA_OBJECT_POINTER_ERROR) - { - return ECMA_VALUE_ERROR; - } - else if (proto_p == base_p) - { - ecma_deref_object (proto_p); - return ECMA_VALUE_TRUE; - } - - /* Advance up on prototype chain. */ - target_p = proto_p; - } while (true); -} /* ecma_op_object_is_prototype_of */ - -/** - * Object's EnumerableOwnPropertyNames operation - * - * See also: - * ECMA-262 v11, 7.3.23 - * - * @return NULL - if operation fails - * collection of property names / values / name-value pairs - otherwise - */ -ecma_collection_t * -ecma_op_object_get_enumerable_property_names (ecma_object_t *obj_p, /**< routine's first argument */ - ecma_enumerable_property_names_options_t option) /**< listing option */ -{ - /* 2. */ - ecma_collection_t *prop_names_p = ecma_op_object_own_property_keys (obj_p, JERRY_PROPERTY_FILTER_EXCLUDE_SYMBOLS); - -#if JERRY_BUILTIN_PROXY - if (JERRY_UNLIKELY (prop_names_p == NULL)) - { - return prop_names_p; - } -#endif /* JERRY_BUILTIN_PROXY */ - - ecma_value_t *names_buffer_p = prop_names_p->buffer_p; - /* 3. */ - ecma_collection_t *properties_p = ecma_new_collection (); - - /* 4. */ - for (uint32_t i = 0; i < prop_names_p->item_count; i++) - { - /* 4.a */ - if (ecma_is_value_string (names_buffer_p[i])) - { - ecma_string_t *key_p = ecma_get_string_from_value (names_buffer_p[i]); - - /* 4.a.i */ - ecma_property_descriptor_t prop_desc; - ecma_value_t status = ecma_op_object_get_own_property_descriptor (obj_p, key_p, &prop_desc); - - if (ECMA_IS_VALUE_ERROR (status)) - { - ecma_collection_free (prop_names_p); - ecma_collection_free (properties_p); - - return NULL; - } - - const bool is_enumerable = (prop_desc.flags & JERRY_PROP_IS_ENUMERABLE) != 0; - ecma_free_property_descriptor (&prop_desc); - /* 4.a.ii */ - if (is_enumerable) - { - /* 4.a.ii.1 */ - if (option == ECMA_ENUMERABLE_PROPERTY_KEYS) - { - ecma_collection_push_back (properties_p, ecma_copy_value (names_buffer_p[i])); - } - else - { - /* 4.a.ii.2.a */ - ecma_value_t value = ecma_op_object_get (obj_p, key_p); - - if (ECMA_IS_VALUE_ERROR (value)) - { - ecma_collection_free (prop_names_p); - ecma_collection_free (properties_p); - - return NULL; - } - - /* 4.a.ii.2.b */ - if (option == ECMA_ENUMERABLE_PROPERTY_VALUES) - { - ecma_collection_push_back (properties_p, value); - } - else - { - /* 4.a.ii.2.c.i */ - JERRY_ASSERT (option == ECMA_ENUMERABLE_PROPERTY_ENTRIES); - - /* 4.a.ii.2.c.ii */ - ecma_object_t *entry_p = ecma_op_new_array_object (2); - - ecma_builtin_helper_def_prop_by_index (entry_p, - 0, - names_buffer_p[i], - ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); - ecma_builtin_helper_def_prop_by_index (entry_p, 1, value, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); - ecma_free_value (value); - - /* 4.a.ii.2.c.iii */ - ecma_collection_push_back (properties_p, ecma_make_object_value (entry_p)); - } - } - } - } - } - - ecma_collection_free (prop_names_p); - - return properties_p; -} /* ecma_op_object_get_enumerable_property_names */ - -/** - * Helper method for getting lazy instantiated properties for [[OwnPropertyKeys]] - */ -static void -ecma_object_list_lazy_property_names (ecma_object_t *obj_p, /**< object */ - ecma_collection_t *prop_names_p, /**< prop name collection */ - ecma_property_counter_t *prop_counter_p, /**< property counters */ - jerry_property_filter_t filter) /**< property name filter options */ -{ - switch (ecma_get_object_type (obj_p)) - { - case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION: - { - if (ecma_builtin_function_is_routine (obj_p)) - { - ecma_builtin_routine_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p, filter); - break; - } - /* FALLTHRU */ - } - case ECMA_OBJECT_TYPE_BUILT_IN_GENERAL: - case ECMA_OBJECT_TYPE_BUILT_IN_CLASS: - case ECMA_OBJECT_TYPE_BUILT_IN_ARRAY: - { - ecma_builtin_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p, filter); - break; - } - case ECMA_OBJECT_TYPE_CLASS: - { - ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; - - switch (ext_object_p->u.cls.type) - { - case ECMA_OBJECT_CLASS_STRING: - { - ecma_op_string_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p, filter); - break; - } - case ECMA_OBJECT_CLASS_ARGUMENTS: - { - ecma_op_arguments_object_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p, filter); - break; - } -#if JERRY_BUILTIN_TYPEDARRAY - /* ES2015 9.4.5.1 */ - case ECMA_OBJECT_CLASS_TYPEDARRAY: - { - ecma_op_typedarray_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p, filter); - break; - } -#endif /* JERRY_BUILTIN_TYPEDARRAY */ - } - break; - } - case ECMA_OBJECT_TYPE_FUNCTION: - { - ecma_op_function_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p, filter); - break; - } - case ECMA_OBJECT_TYPE_NATIVE_FUNCTION: - { - ecma_op_external_function_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p, filter); - break; - } - case ECMA_OBJECT_TYPE_BOUND_FUNCTION: - { - ecma_op_bound_function_list_lazy_property_names (obj_p, prop_names_p, prop_counter_p, filter); - break; - } - case ECMA_OBJECT_TYPE_ARRAY: - { - if (!(filter & JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS)) - { - ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); - prop_counter_p->string_named_props++; - } - break; - } - default: - { - JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_GENERAL - || ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_CONSTRUCTOR_FUNCTION); - break; - } - } -} /* ecma_object_list_lazy_property_names */ - -/** - * Helper routine for heapsort algorithm. - */ -static void -ecma_op_object_heap_sort_shift_down (ecma_value_t *buffer_p, /**< array of items */ - uint32_t item_count, /**< number of items */ - uint32_t item_index) /**< index of updated item */ -{ - while (true) - { - uint32_t highest_index = item_index; - uint32_t current_index = (item_index << 1) + 1; - - if (current_index >= item_count) - { - return; - } - - uint32_t value = ecma_string_get_array_index (ecma_get_string_from_value (buffer_p[highest_index])); - uint32_t left_value = ecma_string_get_array_index (ecma_get_string_from_value (buffer_p[current_index])); - - if (value < left_value) - { - highest_index = current_index; - value = left_value; - } - - current_index++; - - if (current_index < item_count - && value < ecma_string_get_array_index (ecma_get_string_from_value (buffer_p[current_index]))) - { - highest_index = current_index; - } - - if (highest_index == item_index) - { - return; - } - - ecma_value_t tmp = buffer_p[highest_index]; - buffer_p[highest_index] = buffer_p[item_index]; - buffer_p[item_index] = tmp; - - item_index = highest_index; - } -} /* ecma_op_object_heap_sort_shift_down */ - -/** - * Object's [[OwnPropertyKeys]] internal method - * - * Order of names in the collection: - * - integer indices in ascending order - * - other indices in creation order (for built-ins: the order of the properties are listed in specification). - * - * Note: - * Implementation of the routine assumes that new properties are appended to beginning of corresponding object's - * property list, and the list is not reordered (in other words, properties are stored in order that is reversed - * to the properties' addition order). - * - * @return NULL - if the Proxy.[[OwnPropertyKeys]] operation raises error - * collection of property names - otherwise - */ -ecma_collection_t * -ecma_op_object_own_property_keys (ecma_object_t *obj_p, /**< object */ - jerry_property_filter_t filter) /**< name filters */ -{ -#if JERRY_BUILTIN_PROXY - if (ECMA_OBJECT_IS_PROXY (obj_p)) - { - return ecma_proxy_object_own_property_keys (obj_p); - } -#endif /* JERRY_BUILTIN_PROXY */ - - if (ecma_op_object_is_fast_array (obj_p)) - { - return ecma_fast_array_object_own_property_keys (obj_p, filter); - } - - ecma_collection_t *prop_names_p = ecma_new_collection (); - ecma_property_counter_t prop_counter = { 0, 0, 0 }; - - ecma_object_list_lazy_property_names (obj_p, prop_names_p, &prop_counter, filter); - - jmem_cpointer_t prop_iter_cp = obj_p->u1.property_list_cp; - -#if JERRY_PROPERTY_HASHMAP - if (prop_iter_cp != JMEM_CP_NULL) - { - ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); - - if (prop_iter_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP) - { - prop_iter_cp = prop_iter_p->next_property_cp; - } - } -#endif /* JERRY_PROPERTY_HASHMAP */ - - jmem_cpointer_t counter_prop_iter_cp = prop_iter_cp; - - uint32_t array_index_named_props = 0; - uint32_t string_named_props = 0; -#if JERRY_ESNEXT - uint32_t symbol_named_props = 0; -#endif /* JERRY_ESNEXT */ - - while (counter_prop_iter_cp != JMEM_CP_NULL) - { - ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, counter_prop_iter_cp); - JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); - - for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) - { - ecma_property_t *property_p = prop_iter_p->types + i; - - if (!ECMA_PROPERTY_IS_RAW (*property_p) || (*property_p & ECMA_PROPERTY_FLAG_BUILT_IN)) - { - continue; - } - - ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p; - - if (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_DIRECT_STRING_MAGIC - && prop_pair_p->names_cp[i] >= LIT_NON_INTERNAL_MAGIC_STRING__COUNT - && prop_pair_p->names_cp[i] < LIT_MAGIC_STRING__COUNT) - { - continue; - } - - ecma_string_t *name_p = ecma_string_from_property_name (*property_p, prop_pair_p->names_cp[i]); - - if (ecma_string_get_array_index (name_p) != ECMA_STRING_NOT_ARRAY_INDEX) - { - array_index_named_props++; - } -#if JERRY_ESNEXT - else if (ecma_prop_name_is_symbol (name_p)) - { - if (!(name_p->u.hash & ECMA_SYMBOL_FLAG_PRIVATE_KEY)) - { - symbol_named_props++; - } - } -#endif /* JERRY_ESNEXT */ - else - { - string_named_props++; - } - - ecma_deref_ecma_string (name_p); - } - - counter_prop_iter_cp = prop_iter_p->next_property_cp; - } - - if (filter & JERRY_PROPERTY_FILTER_EXCLUDE_INTEGER_INDICES) - { - JERRY_ASSERT (prop_counter.array_index_named_props == 0); - array_index_named_props = 0; - } - - if (filter & JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS) - { - JERRY_ASSERT (prop_counter.string_named_props == 0); - string_named_props = 0; - } - -#if JERRY_ESNEXT - if (filter & JERRY_PROPERTY_FILTER_EXCLUDE_SYMBOLS) - { - JERRY_ASSERT (prop_counter.symbol_named_props == 0); - symbol_named_props = 0; - } - - uint32_t total = array_index_named_props + string_named_props + symbol_named_props; -#else /* !JERRY_ESNEXT */ - uint32_t total = array_index_named_props + string_named_props; -#endif /* JERRY_ESNEXT */ - - if (total == 0) - { - return prop_names_p; - } - - ecma_collection_reserve (prop_names_p, total); - prop_names_p->item_count += total; - ecma_value_t *buffer_p = prop_names_p->buffer_p; - ecma_value_t *array_index_current_p = buffer_p + array_index_named_props + prop_counter.array_index_named_props; - ecma_value_t *string_current_p = array_index_current_p + string_named_props + prop_counter.string_named_props; + /* Advance up on prototype chain. */ + target_p = proto_p; + } while (true); +} /* ecma_op_object_is_prototype_of */ -#if JERRY_ESNEXT - ecma_value_t *symbol_current_p = string_current_p + symbol_named_props + prop_counter.symbol_named_props; +/** + * Object's EnumerableOwnPropertyNames operation + * + * See also: + * ECMA-262 v11, 7.3.23 + * + * @return NULL - if operation fails + * collection of property names / values / name-value pairs - otherwise + */ +ecma_collection_t * +ecma_op_object_get_enumerable_property_names (ecma_object_t *obj_p, /**< routine's first argument */ + ecma_enumerable_property_names_options_t option) /**< listing option */ +{ + /* 2. */ + ecma_collection_t *prop_names_p = + ecma_internal_method_own_property_keys (obj_p, JERRY_PROPERTY_FILTER_EXCLUDE_SYMBOLS); - if (prop_counter.symbol_named_props > 0 && (array_index_named_props + string_named_props) > 0) +#if JERRY_BUILTIN_PROXY + if (JERRY_UNLIKELY (prop_names_p == NULL)) { - memmove ((void *) string_current_p, - (void *) (buffer_p + prop_counter.array_index_named_props + prop_counter.string_named_props), - prop_counter.symbol_named_props * sizeof (ecma_value_t)); + return prop_names_p; } -#endif /* JERRY_ESNEXT */ +#endif /* JERRY_BUILTIN_PROXY */ - if (prop_counter.string_named_props > 0 && array_index_named_props > 0) - { - memmove ((void *) array_index_current_p, - (void *) (buffer_p + prop_counter.array_index_named_props), - prop_counter.string_named_props * sizeof (ecma_value_t)); - } + ecma_value_t *names_buffer_p = prop_names_p->buffer_p; + /* 3. */ + ecma_collection_t *properties_p = ecma_new_collection (); - while (prop_iter_cp != JMEM_CP_NULL) + /* 4. */ + for (uint32_t i = 0; i < prop_names_p->item_count; i++) { - ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); - JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); - - for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) + /* 4.a */ + if (ecma_is_value_string (names_buffer_p[i])) { - ecma_property_t *property_p = prop_iter_p->types + i; + ecma_string_t *key_p = ecma_get_string_from_value (names_buffer_p[i]); + + /* 4.a.i */ + ecma_property_descriptor_t prop_desc = ecma_internal_method_get_own_property (obj_p, key_p); - if (!ECMA_PROPERTY_IS_RAW (*property_p) || (*property_p & ECMA_PROPERTY_FLAG_BUILT_IN)) + if (ecma_property_descriptor_error (&prop_desc)) { - continue; - } + ecma_collection_free (prop_names_p); + ecma_collection_free (properties_p); + ecma_free_property_descriptor (&prop_desc); - ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p; + return NULL; + } - if (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_DIRECT_STRING_MAGIC - && prop_pair_p->names_cp[i] >= LIT_NON_INTERNAL_MAGIC_STRING__COUNT - && prop_pair_p->names_cp[i] < LIT_MAGIC_STRING__COUNT) + if (!ecma_property_descriptor_found (&prop_desc)) { + ecma_free_property_descriptor (&prop_desc); continue; } - ecma_string_t *name_p = ecma_string_from_property_name (*property_p, prop_pair_p->names_cp[i]); - - if (ecma_string_get_array_index (name_p) != ECMA_STRING_NOT_ARRAY_INDEX) - { - if (!(filter & JERRY_PROPERTY_FILTER_EXCLUDE_INTEGER_INDICES)) - { - *(--array_index_current_p) = ecma_make_string_value (name_p); - continue; - } - } -#if JERRY_ESNEXT - else if (ecma_prop_name_is_symbol (name_p)) + const bool is_enumerable = ecma_property_descriptor_is_enumerable (&prop_desc); + ecma_free_property_descriptor (&prop_desc); + /* 4.a.ii */ + if (is_enumerable) { - if (!(filter & JERRY_PROPERTY_FILTER_EXCLUDE_SYMBOLS) && !(name_p->u.hash & ECMA_SYMBOL_FLAG_PRIVATE_KEY)) + /* 4.a.ii.1 */ + if (option == ECMA_ENUMERABLE_PROPERTY_KEYS) { - *(--symbol_current_p) = ecma_make_symbol_value (name_p); - continue; + ecma_collection_push_back (properties_p, ecma_copy_value (names_buffer_p[i])); } - } -#endif /* JERRY_ESNEXT */ - else - { - if (!(filter & JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS)) + else { - *(--string_current_p) = ecma_make_string_value (name_p); - continue; - } - } - - ecma_deref_ecma_string (name_p); - } - - prop_iter_cp = prop_iter_p->next_property_cp; - } - - if (array_index_named_props > 1 || (array_index_named_props == 1 && prop_counter.array_index_named_props > 0)) - { - uint32_t prev_value = 0; - ecma_value_t *array_index_p = buffer_p + prop_counter.array_index_named_props; - ecma_value_t *array_index_end_p = array_index_p + array_index_named_props; - - if (prop_counter.array_index_named_props > 0) - { - prev_value = ecma_string_get_array_index (ecma_get_string_from_value (array_index_p[-1])); - } - - do - { - uint32_t value = ecma_string_get_array_index (ecma_get_string_from_value (*array_index_p++)); + /* 4.a.ii.2.a */ + ecma_value_t value = ecma_internal_method_get (obj_p, key_p, ecma_make_object_value (obj_p)); - if (value < prev_value) - { - uint32_t array_props = prop_counter.array_index_named_props + array_index_named_props; - uint32_t i = (array_props >> 1) - 1; + if (ECMA_IS_VALUE_ERROR (value)) + { + ecma_collection_free (prop_names_p); + ecma_collection_free (properties_p); - do - { - ecma_op_object_heap_sort_shift_down (buffer_p, array_props, i); - } while (i-- > 0); + return NULL; + } - i = array_props - 1; + /* 4.a.ii.2.b */ + if (option == ECMA_ENUMERABLE_PROPERTY_VALUES) + { + ecma_collection_push_back (properties_p, value); + } + else + { + /* 4.a.ii.2.c.i */ + JERRY_ASSERT (option == ECMA_ENUMERABLE_PROPERTY_ENTRIES); - do - { - ecma_value_t tmp = buffer_p[i]; - buffer_p[i] = buffer_p[0]; - buffer_p[0] = tmp; + /* 4.a.ii.2.c.ii */ + ecma_object_t *entry_p = ecma_op_new_array_object (2); - ecma_op_object_heap_sort_shift_down (buffer_p, i, 0); - } while (--i > 0); + ecma_builtin_helper_def_prop_by_index (entry_p, + 0, + names_buffer_p[i], + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + ecma_builtin_helper_def_prop_by_index (entry_p, 1, value, ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + ecma_free_value (value); - break; + /* 4.a.ii.2.c.iii */ + ecma_collection_push_back (properties_p, ecma_make_object_value (entry_p)); + } + } } - - prev_value = value; - } while (array_index_p < array_index_end_p); + } } - return prop_names_p; -} /* ecma_op_object_own_property_keys */ + ecma_collection_free (prop_names_p); + + return properties_p; +} /* ecma_op_object_get_enumerable_property_names */ /** * EnumerateObjectProperties abstract method @@ -2604,7 +921,7 @@ ecma_op_object_enumerate (ecma_object_t *obj_p) /**< object */ while (true) { - ecma_collection_t *keys = ecma_op_object_own_property_keys (obj_p, JERRY_PROPERTY_FILTER_EXCLUDE_SYMBOLS); + ecma_collection_t *keys = ecma_internal_method_own_property_keys (obj_p, JERRY_PROPERTY_FILTER_EXCLUDE_SYMBOLS); #if JERRY_ESNEXT if (JERRY_UNLIKELY (keys == NULL)) @@ -2628,26 +945,27 @@ ecma_op_object_enumerate (ecma_object_t *obj_p) /**< object */ } #endif /* JERRY_ESNEXT */ - ecma_property_descriptor_t prop_desc; - ecma_value_t get_desc = ecma_op_object_get_own_property_descriptor (obj_p, name_p, &prop_desc); + ecma_property_descriptor_t prop_desc = ecma_internal_method_get_own_property (obj_p, name_p); - if (ECMA_IS_VALUE_ERROR (get_desc)) + if (ecma_property_descriptor_error (&prop_desc)) { ecma_collection_free (keys); ecma_collection_free (return_names_p); ecma_collection_free (visited_names_p); ecma_deref_object (obj_p); + ecma_free_property_descriptor (&prop_desc); + return NULL; } - if (ecma_is_value_true (get_desc)) + if (ecma_property_descriptor_found (&prop_desc)) { - bool is_enumerable = (prop_desc.flags & JERRY_PROP_IS_ENUMERABLE) != 0; - ecma_free_property_descriptor (&prop_desc); + bool is_enumerable = ecma_property_descriptor_is_enumerable (&prop_desc); if (ecma_collection_has_string_value (visited_names_p, name_p) || ecma_collection_has_string_value (return_names_p, name_p)) { + ecma_free_property_descriptor (&prop_desc); continue; } @@ -2662,12 +980,14 @@ ecma_op_object_enumerate (ecma_object_t *obj_p) /**< object */ ecma_collection_push_back (visited_names_p, prop_name); } } + + ecma_free_property_descriptor (&prop_desc); } ecma_collection_free (keys); /* Query the prototype. */ - ecma_object_t *proto_p = ecma_op_object_get_prototype_of (obj_p); + ecma_object_t *proto_p = ecma_internal_method_get_prototype_of (obj_p); ecma_deref_object (obj_p); if (proto_p == NULL) @@ -2815,15 +1135,15 @@ ecma_object_check_class_name_is_object (ecma_object_t *obj_p) /**< object */ * Used by ecma_object_get_class_name to get the magic string id of class objects */ static const uint16_t ecma_class_object_magic_string_id[] = { - /* These objects require custom property resolving. */ - LIT_MAGIC_STRING_STRING_UL, /**< magic string id of ECMA_OBJECT_CLASS_STRING */ - LIT_MAGIC_STRING_ARGUMENTS_UL, /**< magic string id of ECMA_OBJECT_CLASS_ARGUMENTS */ +/* These objects require custom property resolving. */ #if JERRY_BUILTIN_TYPEDARRAY LIT_MAGIC_STRING__EMPTY, /**< ECMA_OBJECT_CLASS_TYPEDARRAY needs special resolver */ #endif /* JERRY_BUILTIN_TYPEDARRAY */ #if JERRY_MODULE_SYSTEM LIT_MAGIC_STRING_MODULE_UL, /**< magic string id of ECMA_OBJECT_CLASS_MODULE_NAMESPACE */ #endif /* JERRY_MODULE_SYSTEM */ + LIT_MAGIC_STRING_STRING_UL, /**< magic string id of ECMA_OBJECT_CLASS_STRING */ + LIT_MAGIC_STRING_ARGUMENTS_UL, /**< magic string id of ECMA_OBJECT_CLASS_ARGUMENTS */ /* These objects are marked by Garbage Collector. */ #if JERRY_ESNEXT @@ -3231,7 +1551,7 @@ ecma_op_invoke (ecma_value_t object, /**< Object value */ ecma_value_t this_arg = object_value; #endif /* JERRY_ESNEXT */ - ecma_value_t func = ecma_op_object_get_with_receiver (object_p, property_name_p, this_arg); + ecma_value_t func = ecma_internal_method_get (object_p, property_name_p, this_arg); if (ECMA_IS_VALUE_ERROR (func)) { @@ -3240,7 +1560,7 @@ ecma_op_invoke (ecma_value_t object, /**< Object value */ } /* 4. */ - ecma_value_t call_result = ecma_op_function_validated_call (func, this_arg, args_p, args_len); + ecma_value_t call_result = ecma_internal_method_validated_call (func, this_arg, args_p, args_len); ecma_free_value (func); ecma_deref_object (object_p); @@ -3248,206 +1568,35 @@ ecma_op_invoke (ecma_value_t object, /**< Object value */ return call_result; } /* ecma_op_invoke */ -/** - * Ordinary object [[GetPrototypeOf]] operation - * - * See also: - * ECMAScript v6, 9.1.1 - * - * @return the value of the [[Prototype]] internal slot of the given object. - */ -extern inline jmem_cpointer_t JERRY_ATTR_ALWAYS_INLINE -ecma_op_ordinary_object_get_prototype_of (ecma_object_t *obj_p) /**< object */ -{ - JERRY_ASSERT (!ecma_is_lexical_environment (obj_p)); - JERRY_ASSERT (!ECMA_OBJECT_IS_PROXY (obj_p)); - - return obj_p->u2.prototype_cp; -} /* ecma_op_ordinary_object_get_prototype_of */ - -/** - * Ordinary object [[SetPrototypeOf]] operation - * - * See also: - * ECMAScript v6, 9.1.2 - * - * @return ECMA_VALUE_FALSE - if the operation fails - * ECMA_VALUE_TRUE - otherwise - */ -extern inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE -ecma_op_ordinary_object_set_prototype_of (ecma_object_t *obj_p, /**< base object */ - ecma_value_t proto) /**< prototype object */ -{ - JERRY_ASSERT (!ecma_is_lexical_environment (obj_p)); - JERRY_ASSERT (!ECMA_OBJECT_IS_PROXY (obj_p)); - - /* 1. */ - JERRY_ASSERT (ecma_is_value_object (proto) || ecma_is_value_null (proto)); - - /* 3. */ - ecma_object_t *current_proto_p = ECMA_GET_POINTER (ecma_object_t, ecma_op_ordinary_object_get_prototype_of (obj_p)); - ecma_object_t *new_proto_p = ecma_is_value_null (proto) ? NULL : ecma_get_object_from_value (proto); - - /* 4. */ - if (new_proto_p == current_proto_p) - { - return ECMA_VALUE_TRUE; - } - - /* 2 - 5. */ - if (!ecma_op_ordinary_object_is_extensible (obj_p)) - { - return ECMA_VALUE_FALSE; - } - - /** - * When the prototype of a fast array changes, it is required to convert the - * array to a "normal" array. This ensures that all [[Get]]/[[Set]]/etc. - * calls works as expected. - */ - if (ecma_op_object_is_fast_array (obj_p)) - { - ecma_fast_array_convert_to_normal (obj_p); - } - - /* 6. */ - ecma_object_t *iter_p = new_proto_p; - - /* 7 - 8. */ - while (true) - { - /* 8.a */ - if (iter_p == NULL) - { - break; - } - - /* 8.b */ - if (obj_p == iter_p) - { - return ECMA_VALUE_FALSE; - } - - /* 8.c.i */ -#if JERRY_BUILTIN_PROXY - if (ECMA_OBJECT_IS_PROXY (iter_p)) - { - /** - * Prevent setting 'Object.prototype.__proto__' - * to avoid circular referencing in the prototype chain. - */ - if (obj_p == ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE)) - { - return ECMA_VALUE_FALSE; - } - - break; - } -#endif /* JERRY_BUILTIN_PROXY */ - - /* 8.c.ii */ - iter_p = ECMA_GET_POINTER (ecma_object_t, ecma_op_ordinary_object_get_prototype_of (iter_p)); - } - - /* 9. */ - ECMA_SET_POINTER (obj_p->u2.prototype_cp, new_proto_p); - - /* 10. */ - return ECMA_VALUE_TRUE; -} /* ecma_op_ordinary_object_set_prototype_of */ - -/** - * [[IsExtensible]] operation for Ordinary object. - * - * See also: - * ECMAScript v6, 9.1.2 - * - * @return true - if object is extensible - * false - otherwise - */ -extern inline bool JERRY_ATTR_PURE -ecma_op_ordinary_object_is_extensible (ecma_object_t *object_p) /**< object */ -{ - JERRY_ASSERT (!ECMA_OBJECT_IS_PROXY (object_p)); - - bool is_extensible = (object_p->type_flags_refs & ECMA_OBJECT_FLAG_EXTENSIBLE) != 0; - - JERRY_ASSERT (!ecma_op_object_is_fast_array (object_p) || is_extensible); - - return is_extensible; -} /* ecma_op_ordinary_object_is_extensible */ - -/** - * Set value of [[Extensible]] object's internal property. - */ -void JERRY_ATTR_NOINLINE -ecma_op_ordinary_object_prevent_extensions (ecma_object_t *object_p) /**< object */ -{ - JERRY_ASSERT (!ECMA_OBJECT_IS_PROXY (object_p)); - - if (JERRY_UNLIKELY (ecma_op_object_is_fast_array (object_p))) - { - ecma_fast_array_convert_to_normal (object_p); - } - - object_p->type_flags_refs &= (ecma_object_descriptor_t) ~ECMA_OBJECT_FLAG_EXTENSIBLE; -} /* ecma_op_ordinary_object_prevent_extensions */ - /** * Checks whether an object (excluding prototypes) has a named property * * @return true - if property is found * false - otherwise */ -extern inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE -ecma_op_ordinary_object_has_own_property (ecma_object_t *object_p, /**< the object */ - ecma_string_t *property_name_p) /**< property name */ -{ - JERRY_ASSERT (!ECMA_OBJECT_IS_PROXY (object_p)); - - ecma_property_t property = - ecma_op_object_get_own_property (object_p, property_name_p, NULL, ECMA_PROPERTY_GET_NO_OPTIONS); - -#if JERRY_BUILTIN_TYPEDARRAY - if (JERRY_UNLIKELY (property == ECMA_PROPERTY_TYPE_NOT_FOUND_AND_THROW)) - { - return ECMA_VALUE_ERROR; - } -#endif /* JERRY_BUILTIN_TYPEDARRAY */ - - JERRY_ASSERT (ECMA_PROPERTY_IS_FOUND (property) || property == ECMA_PROPERTY_TYPE_NOT_FOUND - || property == ECMA_PROPERTY_TYPE_NOT_FOUND_AND_STOP); - - return ecma_make_boolean_value (ECMA_PROPERTY_IS_FOUND (property)); -} /* ecma_op_ordinary_object_has_own_property */ - -/** - * Checks whether an object (excluding prototypes) has a named property. Handles proxy objects too. - * - * @return true - if property is found - * false - otherwise - */ ecma_value_t ecma_op_object_has_own_property (ecma_object_t *object_p, /**< the object */ ecma_string_t *property_name_p) /**< property name */ { -#if JERRY_BUILTIN_PROXY - if (ECMA_OBJECT_IS_PROXY (object_p)) - { - ecma_property_descriptor_t prop_desc; + ecma_property_descriptor_t prop_desc = ecma_internal_method_get_own_property (object_p, property_name_p); - ecma_value_t status = ecma_proxy_object_get_own_property_descriptor (object_p, property_name_p, &prop_desc); - - if (ecma_is_value_true (status)) - { - ecma_free_property_descriptor (&prop_desc); - } + ecma_value_t ret_value; - return status; + if (ecma_property_descriptor_error (&prop_desc)) + { + ret_value = ECMA_VALUE_ERROR; + } + else if (ecma_property_descriptor_found (&prop_desc)) + { + ret_value = ECMA_VALUE_TRUE; + ecma_free_property_descriptor (&prop_desc); + } + else + { + ret_value = ECMA_VALUE_FALSE; } -#endif /* JERRY_BUILTIN_PROXY */ - return ecma_op_ordinary_object_has_own_property (object_p, property_name_p); + return ret_value; } /* ecma_op_object_has_own_property */ #if JERRY_BUILTIN_WEAKREF || JERRY_BUILTIN_CONTAINER @@ -3526,6 +1675,7 @@ ecma_op_object_unref_weak (ecma_object_t *object_p, /**< this argument */ } /* ecma_op_object_unref_weak */ #endif /* JERRY_BUILTIN_WEAKREF || JERRY_BUILTIN_CONTAINER */ + /** * Raise property redefinition error * @@ -3534,7 +1684,7 @@ ecma_op_object_unref_weak (ecma_object_t *object_p, /**< this argument */ */ ecma_value_t ecma_raise_property_redefinition (ecma_string_t *property_name_p, /**< property name */ - uint16_t flags) /**< property descriptor flags */ + uint32_t flags) /**< property descriptor flags */ { JERRY_UNUSED (property_name_p); @@ -3560,6 +1710,47 @@ ecma_raise_readonly_assignment (ecma_string_t *property_name_p, /**< property na ecma_make_prop_name_value (property_name_p)); } /* ecma_raise_readonly_assignment */ +/** + * Raise non confugurable property error + * + * @return ECMA_VALUE_FALSE - if is_throw is true + * raised TypeError - otherwise + */ +ecma_value_t +ecma_raise_non_configurable_property (ecma_string_t *property_name_p, /**< property name */ + bool is_throw) /**< is throw flag */ +{ + JERRY_UNUSED (property_name_p); + + return ECMA_REJECT_WITH_FORMAT (is_throw, + "property: % is not configurable", + ecma_make_prop_name_value (property_name_p)); +} /* ecma_raise_non_configurable_property */ + +/** + * CanonicalNumericIndexString + * + * Checks whether the property name is a valid element index + * + * @return true, if valid + * false, otherwise + */ +bool +ecma_op_canonical_numeric_string (ecma_string_t *property_name_p) /**< property name */ +{ + ecma_number_t num = ecma_string_to_number (property_name_p); + + if (num == 0) + { + return true; + } + + ecma_string_t *num_to_str = ecma_new_ecma_string_from_number (num); + bool is_same = ecma_compare_ecma_strings (property_name_p, num_to_str); + ecma_deref_ecma_string (num_to_str); + return is_same; +} /* ecma_op_canonical_numeric_string */ + /** * @} * @} diff --git a/jerry-core/ecma/operations/ecma-objects.h b/jerry-core/ecma/operations/ecma-objects.h index 31c51faffb..ef3735620f 100644 --- a/jerry-core/ecma/operations/ecma-objects.h +++ b/jerry-core/ecma/operations/ecma-objects.h @@ -50,22 +50,12 @@ #define ECMA_REJECT(is_throw, msg) ((is_throw) ? ecma_raise_type_error (ECMA_ERR_EMPTY) : ECMA_VALUE_FALSE) #endif /* JERRY_ERROR_MESSAGES */ -ecma_value_t ecma_raise_property_redefinition (ecma_string_t *property_name_p, uint16_t flags); +ecma_value_t ecma_raise_property_redefinition (ecma_string_t *property_name_p, uint32_t flags); ecma_value_t ecma_raise_readonly_assignment (ecma_string_t *property_name_p, bool is_throw); +ecma_value_t ecma_raise_non_configurable_property (ecma_string_t *property_name_p, bool is_throw); -ecma_property_t ecma_op_object_get_own_property (ecma_object_t *object_p, - ecma_string_t *property_name_p, - ecma_property_ref_t *property_ref_p, - uint32_t options); -ecma_value_t ecma_op_ordinary_object_has_own_property (ecma_object_t *object_p, ecma_string_t *property_name_p); -ecma_value_t ecma_op_object_has_own_property (ecma_object_t *object_p, ecma_string_t *property_name_p); -ecma_value_t ecma_op_object_has_property (ecma_object_t *object_p, ecma_string_t *property_name_p); -ecma_value_t ecma_op_object_find_own (ecma_value_t base_value, ecma_object_t *object_p, ecma_string_t *property_name_p); -ecma_value_t ecma_op_object_find (ecma_object_t *object_p, ecma_string_t *property_name_p); +ecma_value_t ecma_op_object_find (ecma_object_t *obj_p, ecma_string_t *property_name_p, ecma_value_t base_value); ecma_value_t ecma_op_object_find_by_index (ecma_object_t *object_p, ecma_length_t index); -ecma_value_t ecma_op_object_get (ecma_object_t *object_p, ecma_string_t *property_name_p); -ecma_value_t -ecma_op_object_get_with_receiver (ecma_object_t *object_p, ecma_string_t *property_name_p, ecma_value_t receiver); ecma_value_t ecma_op_object_get_length (ecma_object_t *object_p, ecma_length_t *length_p); ecma_value_t ecma_op_object_get_by_index (ecma_object_t *object_p, ecma_length_t index); ecma_value_t ecma_op_object_get_by_magic_id (ecma_object_t *object_p, lit_magic_string_id_t property_id); @@ -76,36 +66,15 @@ ecma_value_t ecma_op_object_get_by_symbol_id (ecma_object_t *object_p, lit_magic ecma_value_t ecma_op_get_method_by_symbol_id (ecma_value_t value, lit_magic_string_id_t symbol_id); ecma_value_t ecma_op_get_method_by_magic_id (ecma_value_t value, lit_magic_string_id_t magic_id); #endif /* JERRY_ESNEXT */ -ecma_value_t ecma_op_object_put_with_receiver (ecma_object_t *object_p, - ecma_string_t *property_name_p, - ecma_value_t value, - ecma_value_t receiver, - bool is_throw); -ecma_value_t -ecma_op_object_put (ecma_object_t *object_p, ecma_string_t *property_name_p, ecma_value_t value, bool is_throw); -ecma_value_t ecma_op_object_put_with_receiver (ecma_object_t *object_p, - ecma_string_t *property_name_p, - ecma_value_t value, - ecma_value_t receiver, - bool is_throw); ecma_value_t ecma_op_object_put_by_index (ecma_object_t *object_p, ecma_length_t index, ecma_value_t value, bool is_throw); -ecma_value_t ecma_op_object_delete (ecma_object_t *obj_p, ecma_string_t *property_name_p, bool is_throw); ecma_value_t ecma_op_object_delete_by_index (ecma_object_t *obj_p, ecma_length_t index, bool is_throw); ecma_value_t ecma_op_object_default_value (ecma_object_t *obj_p, ecma_preferred_type_hint_t hint); -ecma_value_t ecma_op_object_define_own_property (ecma_object_t *obj_p, - ecma_string_t *property_name_p, - const ecma_property_descriptor_t *property_desc_p); -ecma_value_t ecma_op_object_get_own_property_descriptor (ecma_object_t *object_p, - ecma_string_t *property_name_p, - ecma_property_descriptor_t *prop_desc_p); ecma_value_t ecma_op_object_has_instance (ecma_object_t *obj_p, ecma_value_t value); -ecma_object_t *ecma_op_object_get_prototype_of (ecma_object_t *obj_p); ecma_value_t ecma_op_object_is_prototype_of (ecma_object_t *base_p, ecma_object_t *target_p); ecma_collection_t *ecma_op_object_get_enumerable_property_names (ecma_object_t *obj_p, ecma_enumerable_property_names_options_t option); -ecma_collection_t *ecma_op_object_own_property_keys (ecma_object_t *obj_p, jerry_property_filter_t filter); ecma_collection_t *ecma_op_object_enumerate (ecma_object_t *obj_p); lit_magic_string_id_t ecma_object_get_class_name (ecma_object_t *obj_p); @@ -125,6 +94,7 @@ ecma_value_t ecma_op_invoke_by_symbol_id (ecma_value_t object, void ecma_op_object_set_weak (ecma_object_t *object_p, ecma_object_t *target_p); void ecma_op_object_unref_weak (ecma_object_t *object_p, ecma_value_t ref_holder); #endif /* JERRY_BUILTIN_WEAKREF || JERRY_BUILTIN_CONTAINER */ +ecma_value_t ecma_op_object_has_own_property (ecma_object_t *object_p, ecma_string_t *property_name_p); ecma_value_t ecma_op_invoke (ecma_value_t object, ecma_string_t *property_name_p, ecma_value_t *args_p, uint32_t args_len); ecma_value_t ecma_op_invoke_by_magic_id (ecma_value_t object, @@ -132,16 +102,47 @@ ecma_value_t ecma_op_invoke_by_magic_id (ecma_value_t object, ecma_value_t *args_p, uint32_t args_len); -jmem_cpointer_t ecma_op_ordinary_object_get_prototype_of (ecma_object_t *obj_p); -ecma_value_t ecma_op_ordinary_object_set_prototype_of (ecma_object_t *base_p, ecma_value_t proto); -bool JERRY_ATTR_PURE ecma_op_ordinary_object_is_extensible (ecma_object_t *object_p); -void ecma_op_ordinary_object_prevent_extensions (ecma_object_t *object_p); +ecma_object_t *ecma_internal_method_get_prototype_of (ecma_object_t *obj_p); +ecma_value_t ecma_internal_method_set_prototype_of (ecma_object_t *obj_p, ecma_value_t proto); +ecma_value_t ecma_internal_method_is_extensible (ecma_object_t *obj_p); +ecma_value_t ecma_internal_method_prevent_extensions (ecma_object_t *obj_p); +ecma_property_descriptor_t ecma_internal_method_get_own_property (ecma_object_t *obj_p, ecma_string_t *property_name_p); +ecma_value_t ecma_internal_method_define_own_property (ecma_object_t *obj_p, + ecma_string_t *property_name_p, + const ecma_property_descriptor_t *property_desc_p); +ecma_value_t ecma_internal_method_has_property (ecma_object_t *obj_p, ecma_string_t *property_name_p); +ecma_value_t ecma_internal_method_get (ecma_object_t *obj_p, ecma_string_t *property_name_p, ecma_value_t receiver); +ecma_value_t ecma_internal_method_set (ecma_object_t *obj_p, + ecma_string_t *property_name_p, + ecma_value_t value, + ecma_value_t receiver, + bool is_throw); +ecma_value_t ecma_internal_method_delete (ecma_object_t *obj_p, ecma_string_t *property_name_p, bool is_strict); +ecma_collection_t *ecma_internal_method_own_property_keys (ecma_object_t *obj_p, jerry_property_filter_t filter); + +ecma_value_t ecma_internal_method_call (ecma_object_t *obj_p, + ecma_value_t this_value, + const ecma_value_t *arguments_list_p, + uint32_t arguments_list_len); + +ecma_value_t ecma_internal_method_validated_call (ecma_value_t callee, + ecma_value_t this_value, + const ecma_value_t *arguments_list_p, + uint32_t arguments_list_len); + +ecma_value_t ecma_internal_method_construct (ecma_object_t *obj_p, + ecma_object_t *new_target_p, + const ecma_value_t *arguments_list_p, + uint32_t arguments_list_len); + +void ecma_internal_method_list_lazy_property_keys (ecma_object_t *obj_p, + ecma_collection_t *prop_names_p, + ecma_property_counter_t *prop_counter_p, + jerry_property_filter_t filter); + +void ecma_internal_method_delete_lazy_property (ecma_object_t *obj_p, ecma_string_t *property_name_p); -#if JERRY_BUILTIN_PROXY -ecma_value_t ecma_op_get_own_property_descriptor (ecma_value_t target, - ecma_string_t *property_name_p, - ecma_property_descriptor_t *prop_desc_p); -#endif /* JERRY_BUILTIN_PROXY */ +bool ecma_op_canonical_numeric_string (ecma_string_t *property_name_p); /** * @} diff --git a/jerry-core/ecma/operations/ecma-ordinary-object.c b/jerry-core/ecma/operations/ecma-ordinary-object.c new file mode 100644 index 0000000000..138c520808 --- /dev/null +++ b/jerry-core/ecma/operations/ecma-ordinary-object.c @@ -0,0 +1,969 @@ +/* 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-ordinary-object.h" + +#include "ecma-arguments-object.h" +#include "ecma-array-object.h" +#include "ecma-builtin-helpers.h" +#include "ecma-exceptions.h" +#include "ecma-function-object.h" +#include "ecma-gc.h" +#include "ecma-globals.h" +#include "ecma-lcache.h" +#include "ecma-lex-env.h" +#include "ecma-objects-general.h" +#include "ecma-objects.h" +#include "ecma-promise-object.h" +#include "ecma-string-object.h" +#include "ecma-typedarray-object.h" + +#include "jcontext.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaordinaryobject ECMA Ordinary object related routines + * @{ + */ + +/** + * Helper function to get the prototype of the given object + * + * @return compressed pointer + */ +jmem_cpointer_t +ecma_object_get_prototype_of (ecma_object_t *obj_p) /**< object */ +{ + JERRY_ASSERT (!ecma_is_lexical_environment (obj_p)); + JERRY_ASSERT (!ECMA_OBJECT_IS_PROXY (obj_p)); + + return obj_p->u2.prototype_cp; +} /* ecma_object_get_prototype_of */ + +/** + * Ordinary object [[GetPrototypeOf]] operation + * + * Note: returned valid object must be freed. + * + * @return ecma_object_t * - prototype of the input object. + * NULL - the input object does not have a prototype. + */ +ecma_object_t * +ecma_ordinary_object_get_prototype_of (ecma_object_t *obj_p) /**< the object */ +{ + jmem_cpointer_t proto_cp = ecma_object_get_prototype_of (obj_p); + + if (proto_cp == JMEM_CP_NULL) + { + return NULL; + } + + ecma_object_t *proto_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, proto_cp); + ecma_ref_object (proto_p); + + return proto_p; +} /* ecma_ordinary_object_get_prototype_of */ + +/** + * Ordinary object [[SetPrototypeOf]] operation + * + * See also: + * ECMAScript v6, 9.1.2 + * + * @return ECMA_VALUE_FALSE - if the operation fails + * ECMA_VALUE_TRUE - otherwise + */ +ecma_value_t +ecma_ordinary_object_set_prototype_of (ecma_object_t *obj_p, /**< base object */ + ecma_value_t proto) /**< prototype object */ +{ + JERRY_ASSERT (!ecma_is_lexical_environment (obj_p)); + JERRY_ASSERT (!ECMA_OBJECT_IS_PROXY (obj_p)); + + /* 1. */ + JERRY_ASSERT (ecma_is_value_object (proto) || ecma_is_value_null (proto)); + + /* 3. */ + ecma_object_t *current_proto_p = ECMA_GET_POINTER (ecma_object_t, ecma_object_get_prototype_of (obj_p)); + ecma_object_t *new_proto_p = ecma_is_value_null (proto) ? NULL : ecma_get_object_from_value (proto); + + /* 4. */ + if (new_proto_p == current_proto_p) + { + return ECMA_VALUE_TRUE; + } + + /* 2 - 5. */ + if (ecma_is_value_false (ecma_ordinary_object_is_extensible (obj_p))) + { + return ECMA_VALUE_FALSE; + } + + /** + * When the prototype of a fast array changes, it is required to convert the + * array to a "normal" array. This ensures that all [[Get]]/[[Set]]/etc. + * calls works as expected. + */ + if (ecma_op_object_is_fast_array (obj_p)) + { + ecma_fast_array_convert_to_normal (obj_p); + } + + /* 6. */ + ecma_object_t *iter_p = new_proto_p; + + /* 7 - 8. */ + while (true) + { + /* 8.a */ + if (iter_p == NULL) + { + break; + } + + /* 8.b */ + if (obj_p == iter_p) + { + return ECMA_VALUE_FALSE; + } + + /* 8.c.i */ +#if JERRY_BUILTIN_PROXY + if (ECMA_OBJECT_IS_PROXY (iter_p)) + { + /** + * Prevent setting 'Object.prototype.__proto__' + * to avoid circular referencing in the prototype chain. + */ + if (obj_p == ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE)) + { + return ECMA_VALUE_FALSE; + } + break; + } +#endif /* JERRY_BUILTIN_PROXY */ + + /* 8.c.ii */ + iter_p = ECMA_GET_POINTER (ecma_object_t, ecma_object_get_prototype_of (iter_p)); + } + + /* 9. */ + ECMA_SET_POINTER (obj_p->u2.prototype_cp, new_proto_p); + + /* 10. */ + return ECMA_VALUE_TRUE; +} /* ecma_ordinary_object_set_prototype_of */ + +/** + * Ordinary object's [[IsExtensible]] operation + * + * See also: + * ECMAScript v6, 9.1.2 + * + * @return ECMA_VALUE_TRUE - if object is extensible + * ECMA_VALUE_FALSE - otherwise + */ +ecma_value_t +ecma_ordinary_object_is_extensible (ecma_object_t *object_p) /**< object */ +{ + JERRY_ASSERT (!ECMA_OBJECT_IS_PROXY (object_p)); + + bool is_extensible = (object_p->type_flags_refs & ECMA_OBJECT_FLAG_EXTENSIBLE) != 0; + + JERRY_ASSERT (!ecma_op_object_is_fast_array (object_p) || is_extensible); + + return ecma_make_boolean_value (is_extensible); +} /* ecma_ordinary_object_is_extensible */ + +/** + * Set value of [[Extensible]] object's internal property. + * + * @return ECMA_VALUE_TRUE + */ +ecma_value_t +ecma_ordinary_object_prevent_extensions (ecma_object_t *object_p) /**< object */ +{ + if (JERRY_UNLIKELY (ecma_op_object_is_fast_array (object_p))) + { + ecma_fast_array_convert_to_normal (object_p); + } + + object_p->type_flags_refs &= (ecma_object_descriptor_t) ~ECMA_OBJECT_FLAG_EXTENSIBLE; + + return ECMA_VALUE_TRUE; +} /* ecma_ordinary_object_prevent_extensions */ + +/** + * Ordinary object's [[GetOwnProperty]] operation + * + * See also: + * ECMAScript v6, 9.1.7.1 + * + * @return ecma property t + */ +ecma_property_descriptor_t +ecma_ordinary_object_get_own_property (ecma_object_t *object_p, /**< the object */ + ecma_string_t *property_name_p) /**< property name */ +{ + ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); + + prop_desc.u.property_p = ecma_find_named_property (object_p, property_name_p); + + if (prop_desc.u.property_p != NULL) + { + prop_desc.flags = + ECMA_PROP_DESC_PROPERTY_FOUND | ECMA_PROPERTY_TO_PROPERTY_DESCRIPTOR_FLAGS (prop_desc.u.property_p); + } + + return prop_desc; +} /* ecma_ordinary_object_get_own_property */ + +/** + * Ordinary object [[DefineOwnProperty]] operation + * + * See also: + * ECMA-262 v5, 8.6.2; ECMA-262 v5, Table 8 + * ECMA-262 v5, 8.12.9 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_ordinary_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 */ +{ + JERRY_ASSERT (object_p != NULL && !ecma_is_lexical_environment (object_p)); + JERRY_ASSERT (!ecma_op_object_is_fast_array (object_p)); + JERRY_ASSERT (!ECMA_OBJECT_IS_PROXY (object_p)); + JERRY_ASSERT (property_name_p != NULL); + + ecma_property_descriptor_t current_prop = ecma_internal_method_get_own_property (object_p, property_name_p); + + bool is_extensible = (object_p->type_flags_refs & ECMA_OBJECT_FLAG_EXTENSIBLE) != 0; + bool is_valid = ecma_op_validate_and_apply_property_descriptor (object_p, + property_name_p, + property_desc_p, + ¤t_prop, + is_extensible); + + ecma_free_virtual_property_descriptor (¤t_prop); + + if (!is_valid) + { + return ecma_raise_property_redefinition (property_name_p, property_desc_p->flags); + } + + return ECMA_VALUE_TRUE; +} /* ecma_ordinary_object_define_own_property */ + +/** + * Ordinary object's [[HasProperty]] operation + * + * See also: + * ECMAScript v6, 9.1.7.1 + * + * @return ECMA_VALUE_ERROR - if the operation fails + * ECMA_VALUE_{TRUE_FALSE} - whether the property is found + */ +ecma_value_t +ecma_ordinary_object_has_property (ecma_object_t *object_p, /**< the object */ + ecma_string_t *property_name_p) /**< property name */ +{ + while (true) + { + /* 2. */ + ecma_property_descriptor_t has_own = ecma_internal_method_get_own_property (object_p, property_name_p); + JERRY_ASSERT (!ecma_property_descriptor_error (&has_own)); + + if (JERRY_UNLIKELY (has_own.flags & ECMA_PROP_DESC_VIRTUAL_NOT_FOUND_AND_STOP)) + { + return ECMA_VALUE_FALSE; + } + + if (ecma_property_descriptor_found (&has_own)) + { + ecma_free_virtual_property_descriptor (&has_own); + return ECMA_VALUE_TRUE; + } + + jmem_cpointer_t proto_cp = ecma_object_get_prototype_of (object_p); + + if (proto_cp == JMEM_CP_NULL) + { + return ECMA_VALUE_FALSE; + } + + object_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, proto_cp); + + if (ECMA_OBJECT_GET_OWN_MAY_ABRUPT (object_p)) + { + return ecma_internal_method_has_property (object_p, property_name_p); + } + } +} /* ecma_ordinary_object_has_property */ + +/** + * Ordinary object's [[Get]] operation + * + * See also: + * ECMAScript v6, 10.1.8.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_ordinary_object_get (ecma_object_t *object_p, /**< the object */ + ecma_string_t *property_name_p, /**< property name */ + ecma_value_t receiver) /**< receiver */ +{ + ecma_property_descriptor_t prop_desc; + + while (true) + { + /* 2. */ + prop_desc = ecma_internal_method_get_own_property (object_p, property_name_p); + + JERRY_ASSERT (!ecma_property_descriptor_error (&prop_desc)); + + /* 3. */ + if (JERRY_LIKELY (ecma_property_descriptor_found (&prop_desc))) + { + break; + } + + /* 3.a */ + jmem_cpointer_t proto_cp = ecma_object_get_prototype_of (object_p); + + /* 3.b */ + if (proto_cp == JMEM_CP_NULL) + { + return ECMA_VALUE_UNDEFINED; + } + + /* 3.c */ + object_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, proto_cp); + + if (ECMA_OBJECT_GET_OWN_MAY_ABRUPT (object_p)) + { + return ecma_internal_method_get (object_p, property_name_p, receiver); + } + } + + /* 4. - 8. */ + return ecma_property_descriptor_get (&prop_desc, receiver); +} /* ecma_ordinary_object_get */ + +/** + * OrdinarySetWithOwnDescriptor abstract operation + * + * See also: + * ECMAScript v6, 10.1.9.2 + * + * @return ecma value t + */ +static inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE +ecma_ordinary_object_set_with_own_descriptor (ecma_string_t *property_name_p, /**< property name */ + ecma_value_t value, /**< ecma value */ + ecma_value_t receiver, /**< receiver */ + ecma_property_descriptor_t *own_desc_p) /**< property descriptor */ +{ + /* 3. */ + if (ecma_property_descriptor_is_data_descriptor (own_desc_p)) + { + /* 3.a */ + if (!ecma_property_descriptor_is_writable (own_desc_p)) + { + return ECMA_VALUE_FALSE; + } + + /* 3.b */ + if (!ecma_is_value_object (receiver)) + { + return ECMA_VALUE_FALSE; + } + + ecma_object_t *receiver_obj_p = ecma_get_object_from_value (receiver); + + /* 3.c */ + ecma_property_descriptor_t exsisting_desc = ecma_internal_method_get_own_property (receiver_obj_p, property_name_p); + + if (ecma_property_descriptor_error (&exsisting_desc)) + { + return ECMA_VALUE_ERROR; + } + + /* 3.d */ + if (ecma_property_descriptor_found (&exsisting_desc)) + { + /* 3.d.i - 3.d.ii */ + if (ecma_property_descriptor_is_accessor_descriptor (&exsisting_desc) + || !ecma_property_descriptor_is_writable (&exsisting_desc)) + { + ecma_free_property_descriptor (&exsisting_desc); + return ECMA_VALUE_FALSE; + } + + /* 3.d.iii */ + ecma_property_descriptor_t value_desc = ecma_make_empty_define_property_descriptor (); + value_desc.flags = (JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_WRITABLE_DEFINED | JERRY_PROP_IS_WRITABLE); + value_desc.value = value; + + /* 3.d.iiv */ + ecma_value_t define_value_result = + ecma_internal_method_define_own_property (receiver_obj_p, property_name_p, &value_desc); + ecma_free_property_descriptor (&exsisting_desc); + + return define_value_result; + } + + /* 3.e */ + ecma_property_descriptor_t value_desc; + value_desc.flags = (JERRY_PROP_IS_CONFIGURABLE | JERRY_PROP_IS_CONFIGURABLE_DEFINED | JERRY_PROP_IS_ENUMERABLE + | JERRY_PROP_IS_ENUMERABLE_DEFINED | JERRY_PROP_IS_WRITABLE | JERRY_PROP_IS_WRITABLE_DEFINED + | JERRY_PROP_IS_VALUE_DEFINED); + value_desc.value = value; + + /* 3.e.i */ + return ecma_internal_method_define_own_property (receiver_obj_p, property_name_p, &value_desc); + } + + /* 4. */ + JERRY_ASSERT (ecma_property_descriptor_is_accessor_descriptor (own_desc_p)); + JERRY_ASSERT (own_desc_p->u.property_p != NULL); + + /* 5. */ + jmem_cpointer_t setter_cp = + ecma_get_named_accessor_property (ECMA_PROPERTY_VALUE_PTR (own_desc_p->u.property_p))->setter_cp; + + /* 6. */ + if (setter_cp == JMEM_CP_NULL) + { + return ECMA_VALUE_FALSE; + } + + /* 7. */ + ecma_object_t *setter_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, setter_cp); + + ecma_value_t setter_result = ecma_internal_method_call (setter_p, receiver, &value, 1); + + if (ECMA_IS_VALUE_ERROR (setter_result)) + { + return setter_result; + } + + ecma_free_value (setter_result); + + /* 8. */ + return ECMA_VALUE_TRUE; +} /* ecma_ordinary_object_set_with_own_descriptor */ + +/** + * Ordinary object's [[Set]] operation + * + * See also: + * ECMAScript v6, 10.1.9.1 + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_ordinary_object_set (ecma_object_t *object_p, /**< the object */ + ecma_string_t *property_name_p, /**< property name */ + ecma_value_t value, /**< ecma value */ + ecma_value_t receiver, /**< receiver */ + bool is_throw) /**< flag that controls failure handling */ +{ + /* OrdinarySet 2. */ + ecma_property_descriptor_t own_desc = ecma_internal_method_get_own_property (object_p, property_name_p); + + JERRY_ASSERT (!ecma_property_descriptor_error (&own_desc)); + + if ((own_desc.flags & (ECMA_PROP_DESC_VIRTUAL_FOUND | ECMA_PROP_DESC_DATA_WRITABLE)) + == (ECMA_PROP_DESC_FOUND | ECMA_PROP_DESC_DATA_WRITABLE) + && ecma_make_object_value (object_p) == receiver) + { + ecma_named_data_property_assign_value (object_p, ECMA_PROPERTY_VALUE_PTR (own_desc.u.property_p), value); + return ECMA_VALUE_TRUE; + } + + ecma_object_t *obj_iter_p = object_p; + /* OrdinarySetWithOwnDescriptor 2. */ + while (!ecma_property_descriptor_found (&own_desc)) + { + /* OrdinarySetWithOwnDescriptor 2.a */ + jmem_cpointer_t parent_cp = ecma_object_get_prototype_of (obj_iter_p); + + /* OrdinarySetWithOwnDescriptor 2.a.c */ + if (parent_cp == JMEM_CP_NULL) + { + /* No property found on the prototype chain */ + if (JERRY_UNLIKELY (ecma_get_object_base_type (object_p) != ECMA_OBJECT_BASE_TYPE_GENERAL + || ecma_make_object_value (object_p) != receiver)) + { + own_desc.flags = ECMA_PROP_DESC_VIRTUAL | ECMA_PROP_DESC_DATA_CONFIGURABLE_ENUMERABLE_WRITABLE; + own_desc.value = ECMA_VALUE_UNDEFINED; + break; + } + + if (JERRY_UNLIKELY (!(object_p->type_flags_refs & ECMA_OBJECT_FLAG_EXTENSIBLE))) + { + return ecma_raise_readonly_assignment (property_name_p, is_throw); + } + + ecma_property_value_t *new_prop_value_p; + new_prop_value_p = ecma_create_named_data_property (object_p, + property_name_p, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, + NULL); + + new_prop_value_p->value = ecma_copy_value_if_not_object (value); + return ECMA_VALUE_TRUE; + } + + /* OrdinarySetWithOwnDescriptor 2.a.b */ + obj_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, parent_cp); + + if (ecma_get_object_base_type (obj_iter_p) != ECMA_OBJECT_BASE_TYPE_GENERAL) + { + return ecma_internal_method_set (obj_iter_p, property_name_p, value, receiver, is_throw); + } + + /* OrdinarySet 2. */ + own_desc = ecma_internal_method_get_own_property (obj_iter_p, property_name_p); + JERRY_ASSERT (!ecma_property_descriptor_error (&own_desc)); + } + + /* OrdinarySet 3. */ + ecma_value_t result = ecma_ordinary_object_set_with_own_descriptor (property_name_p, value, receiver, &own_desc); + ecma_free_property_descriptor (&own_desc); + + if (ecma_is_value_false (result)) + { + return ecma_raise_readonly_assignment (property_name_p, is_throw); + } + + return result; +} /* ecma_ordinary_object_set */ + +/** + * Ordinary object [[Delete]] operation + * + * 10.1.10.1 OrdinaryDelete + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_ordinary_object_delete (ecma_object_t *obj_p, /**< the object */ + ecma_string_t *property_name_p, /**< property name */ + bool is_throw) /**< flag that controls failure handling */ +{ + JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p)); + JERRY_ASSERT (property_name_p != NULL); + + /* 2. */ + ecma_property_descriptor_t prop_desc = ecma_internal_method_get_own_property (obj_p, property_name_p); + + /* 3. */ + if (!ecma_property_descriptor_found (&prop_desc)) + { + return ECMA_VALUE_TRUE; + } + + /* 4. */ + if (!ecma_property_descriptor_is_configurable (&prop_desc)) + { + /* 5. */ + ecma_free_property_descriptor (&prop_desc); + return ecma_raise_non_configurable_property (property_name_p, is_throw); + } + + uint8_t property_flag = *prop_desc.u.property_p; + + /* 4.a. */ + ecma_delete_property (obj_p, ECMA_PROPERTY_VALUE_PTR (prop_desc.u.property_p)); + + if (property_flag & ECMA_PROPERTY_FLAG_BUILT_IN) + { + ecma_internal_method_delete_lazy_property (obj_p, property_name_p); + } + + ecma_free_property_descriptor (&prop_desc); + + /* 4.b */ + return ECMA_VALUE_TRUE; +} /* ecma_ordinary_object_delete */ + +/** + * Helper routine for heapsort algorithm. + */ +static void +ecma_op_object_heap_sort_shift_down (ecma_value_t *buffer_p, /**< array of items */ + uint32_t item_count, /**< number of items */ + uint32_t item_index) /**< index of updated item */ +{ + while (true) + { + uint32_t highest_index = item_index; + uint32_t current_index = (item_index << 1) + 1; + + if (current_index >= item_count) + { + return; + } + + uint32_t value = ecma_string_get_array_index (ecma_get_string_from_value (buffer_p[highest_index])); + uint32_t left_value = ecma_string_get_array_index (ecma_get_string_from_value (buffer_p[current_index])); + + if (value < left_value) + { + highest_index = current_index; + value = left_value; + } + + current_index++; + + if (current_index < item_count + && value < ecma_string_get_array_index (ecma_get_string_from_value (buffer_p[current_index]))) + { + highest_index = current_index; + } + + if (highest_index == item_index) + { + return; + } + + ecma_value_t tmp = buffer_p[highest_index]; + buffer_p[highest_index] = buffer_p[item_index]; + buffer_p[item_index] = tmp; + + item_index = highest_index; + } +} /* ecma_op_object_heap_sort_shift_down */ + +/** + * Ordinary object's [[OwnPropertyKeys]] internal method + * + * Order of names in the collection: + * - integer indices in ascending order + * - other indices in creation order (for built-ins: the order of the properties are listed in specification). + * + * Note: + * Implementation of the routine assumes that new properties are appended to beginning of corresponding object's + * property list, and the list is not reordered (in other words, properties are stored in order that is reversed + * to the properties' addition order). + * + * @return collection of property names + */ +ecma_collection_t * +ecma_ordinary_object_own_property_keys (ecma_object_t *obj_p, /**< object */ + jerry_property_filter_t filter) /**< name filters */ +{ + ecma_collection_t *prop_names_p = ecma_new_collection (); + ecma_property_counter_t prop_counter = { 0, 0, 0 }; + + ecma_internal_method_list_lazy_property_keys (obj_p, prop_names_p, &prop_counter, filter); + + jmem_cpointer_t prop_iter_cp = obj_p->u1.property_list_cp; + +#if JERRY_PROPERTY_HASHMAP + if (prop_iter_cp != JMEM_CP_NULL) + { + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + + if (prop_iter_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP) + { + prop_iter_cp = prop_iter_p->next_property_cp; + } + } +#endif /* JERRY_PROPERTY_HASHMAP */ + + jmem_cpointer_t counter_prop_iter_cp = prop_iter_cp; + + uint32_t array_index_named_props = 0; + uint32_t string_named_props = 0; +#if JERRY_ESNEXT + uint32_t symbol_named_props = 0; +#endif /* JERRY_ESNEXT */ + + while (counter_prop_iter_cp != JMEM_CP_NULL) + { + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, counter_prop_iter_cp); + JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); + + for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) + { + ecma_property_t *property_p = prop_iter_p->types + i; + + if (!ECMA_PROPERTY_IS_RAW (*property_p) || (*property_p & ECMA_PROPERTY_FLAG_BUILT_IN)) + { + continue; + } + + ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p; + + if (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_DIRECT_STRING_MAGIC + && prop_pair_p->names_cp[i] >= LIT_NON_INTERNAL_MAGIC_STRING__COUNT + && prop_pair_p->names_cp[i] < LIT_MAGIC_STRING__COUNT) + { + continue; + } + + ecma_string_t *name_p = ecma_string_from_property_name (*property_p, prop_pair_p->names_cp[i]); + + if (ecma_string_get_array_index (name_p) != ECMA_STRING_NOT_ARRAY_INDEX) + { + array_index_named_props++; + } +#if JERRY_ESNEXT + else if (ecma_prop_name_is_symbol (name_p)) + { + if (!(name_p->u.hash & ECMA_SYMBOL_FLAG_PRIVATE_KEY)) + { + symbol_named_props++; + } + } +#endif /* JERRY_ESNEXT */ + else + { + string_named_props++; + } + + ecma_deref_ecma_string (name_p); + } + + counter_prop_iter_cp = prop_iter_p->next_property_cp; + } + + if (filter & JERRY_PROPERTY_FILTER_EXCLUDE_INTEGER_INDICES) + { + JERRY_ASSERT (prop_counter.array_index_named_props == 0); + array_index_named_props = 0; + } + + if (filter & JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS) + { + JERRY_ASSERT (prop_counter.string_named_props == 0); + string_named_props = 0; + } + +#if JERRY_ESNEXT + if (filter & JERRY_PROPERTY_FILTER_EXCLUDE_SYMBOLS) + { + JERRY_ASSERT (prop_counter.symbol_named_props == 0); + symbol_named_props = 0; + } + + uint32_t total = array_index_named_props + string_named_props + symbol_named_props; +#else /* !JERRY_ESNEXT */ + uint32_t total = array_index_named_props + string_named_props; +#endif /* JERRY_ESNEXT */ + + if (total == 0) + { + return prop_names_p; + } + + ecma_collection_reserve (prop_names_p, total); + prop_names_p->item_count += total; + + ecma_value_t *buffer_p = prop_names_p->buffer_p; + ecma_value_t *array_index_current_p = buffer_p + array_index_named_props + prop_counter.array_index_named_props; + ecma_value_t *string_current_p = array_index_current_p + string_named_props + prop_counter.string_named_props; + +#if JERRY_ESNEXT + ecma_value_t *symbol_current_p = string_current_p + symbol_named_props + prop_counter.symbol_named_props; + + if (prop_counter.symbol_named_props > 0 && (array_index_named_props + string_named_props) > 0) + { + memmove ((void *) string_current_p, + (void *) (buffer_p + prop_counter.array_index_named_props + prop_counter.string_named_props), + prop_counter.symbol_named_props * sizeof (ecma_value_t)); + } +#endif /* JERRY_ESNEXT */ + + if (prop_counter.string_named_props > 0 && array_index_named_props > 0) + { + memmove ((void *) array_index_current_p, + (void *) (buffer_p + prop_counter.array_index_named_props), + prop_counter.string_named_props * sizeof (ecma_value_t)); + } + + while (prop_iter_cp != JMEM_CP_NULL) + { + ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp); + JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p)); + + for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++) + { + ecma_property_t *property_p = prop_iter_p->types + i; + + if (!ECMA_PROPERTY_IS_RAW (*property_p) || (*property_p & ECMA_PROPERTY_FLAG_BUILT_IN)) + { + continue; + } + + ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p; + + if (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_DIRECT_STRING_MAGIC + && prop_pair_p->names_cp[i] >= LIT_NON_INTERNAL_MAGIC_STRING__COUNT + && prop_pair_p->names_cp[i] < LIT_MAGIC_STRING__COUNT) + { + continue; + } + + ecma_string_t *name_p = ecma_string_from_property_name (*property_p, prop_pair_p->names_cp[i]); + + if (ecma_string_get_array_index (name_p) != ECMA_STRING_NOT_ARRAY_INDEX) + { + if (!(filter & JERRY_PROPERTY_FILTER_EXCLUDE_INTEGER_INDICES)) + { + *(--array_index_current_p) = ecma_make_string_value (name_p); + continue; + } + } +#if JERRY_ESNEXT + else if (ecma_prop_name_is_symbol (name_p)) + { + if (!(filter & JERRY_PROPERTY_FILTER_EXCLUDE_SYMBOLS) && !(name_p->u.hash & ECMA_SYMBOL_FLAG_PRIVATE_KEY)) + { + *(--symbol_current_p) = ecma_make_symbol_value (name_p); + continue; + } + } +#endif /* JERRY_ESNEXT */ + else + { + if (!(filter & JERRY_PROPERTY_FILTER_EXCLUDE_STRINGS)) + { + *(--string_current_p) = ecma_make_string_value (name_p); + continue; + } + } + + ecma_deref_ecma_string (name_p); + } + + prop_iter_cp = prop_iter_p->next_property_cp; + } + + if (array_index_named_props > 1 || (array_index_named_props == 1 && prop_counter.array_index_named_props > 0)) + { + uint32_t prev_value = 0; + ecma_value_t *array_index_p = buffer_p + prop_counter.array_index_named_props; + ecma_value_t *array_index_end_p = array_index_p + array_index_named_props; + + if (prop_counter.array_index_named_props > 0) + { + prev_value = ecma_string_get_array_index (ecma_get_string_from_value (array_index_p[-1])); + } + + do + { + uint32_t value = ecma_string_get_array_index (ecma_get_string_from_value (*array_index_p++)); + + if (value < prev_value) + { + uint32_t array_props = prop_counter.array_index_named_props + array_index_named_props; + uint32_t i = (array_props >> 1) - 1; + + do + { + ecma_op_object_heap_sort_shift_down (buffer_p, array_props, i); + } while (i-- > 0); + + i = array_props - 1; + + do + { + ecma_value_t tmp = buffer_p[i]; + buffer_p[i] = buffer_p[0]; + buffer_p[0] = tmp; + + ecma_op_object_heap_sort_shift_down (buffer_p, i, 0); + } while (--i > 0); + + break; + } + + prev_value = value; + } while (array_index_p < array_index_end_p); + } + + return prop_names_p; +} /* ecma_ordinary_object_own_property_keys */ + +/** + * Handle calling [[Call]] of ordinary object + * + * @return ecma value + */ +ecma_value_t +ecma_ordinary_object_call (ecma_object_t *obj_p, /**< object */ + ecma_value_t this_value, /**< 'this' argument value */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< arguments list length */ +{ + JERRY_UNUSED_4 (obj_p, this_value, arguments_list_p, arguments_list_len); + + return ecma_raise_type_error (ECMA_ERR_EXPECTED_A_FUNCTION); +} /* ecma_ordinary_object_call */ + +/** + * Handle calling [[Construct]] of ordinary object + * + * @return ecma value + */ +ecma_value_t +ecma_ordinary_object_construct (ecma_object_t *obj_p, /**< the object */ + ecma_object_t *new_target_p, /**< mew target */ + const ecma_value_t *arguments_list_p, /**< arguments list */ + uint32_t arguments_list_len) /**< arguments list length */ +{ + JERRY_UNUSED_4 (obj_p, new_target_p, arguments_list_p, arguments_list_len); + + return ecma_raise_type_error (ECMA_ERR_EXPECTED_A_FUNCTION); +} /* ecma_ordinary_object_construct */ + +/** + * List lazy instantiated property names of ordinary object's + */ +void +ecma_ordinary_object_list_lazy_property_keys (ecma_object_t *obj_p, /**< the object */ + ecma_collection_t *prop_names_p, /**< property names */ + ecma_property_counter_t *prop_counter_p, /**< property counter */ + jerry_property_filter_t filter) /**< name filter */ +{ + JERRY_UNUSED_4 (obj_p, prop_names_p, prop_counter_p, filter); +} /* ecma_ordinary_object_list_lazy_property_keys */ + +/** + * Delete configurable properties of ordinary object's + */ +void +ecma_ordinary_object_delete_lazy_property (ecma_object_t *obj_p, /**< the object */ + ecma_string_t *property_name_p) /**< property name */ +{ + JERRY_UNUSED_2 (obj_p, property_name_p); +} /* ecma_ordinary_object_delete_lazy_property */ + +/** + * @} + * @} + */ diff --git a/jerry-core/ecma/operations/ecma-ordinary-object.h b/jerry-core/ecma/operations/ecma-ordinary-object.h new file mode 100644 index 0000000000..024f485ce2 --- /dev/null +++ b/jerry-core/ecma/operations/ecma-ordinary-object.h @@ -0,0 +1,99 @@ +/* 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. + */ + +#ifndef ECMA_ORDINARY_OBJECT_H +#define ECMA_ORDINARY_OBJECT_H + +#include "ecma-globals.h" + +/** \addtogroup ecma ECMA + * @{ + * + * \addtogroup ecmaordinaryobject ECMA Ordinary object related routines + * @{ + */ + +jmem_cpointer_t ecma_object_get_prototype_of (ecma_object_t *obj_p); + +ecma_object_t *ecma_ordinary_object_get_prototype_of (ecma_object_t *obj_p); + +ecma_value_t ecma_ordinary_object_set_prototype_of (ecma_object_t *obj_p, ecma_value_t proto); + +ecma_value_t ecma_ordinary_object_is_extensible (ecma_object_t *obj_p); + +ecma_value_t ecma_ordinary_object_prevent_extensions (ecma_object_t *obj_p); + +ecma_property_descriptor_t ecma_ordinary_object_get_own_property (ecma_object_t *object_p, ecma_string_t *prop_name_p); + +ecma_value_t ecma_ordinary_object_define_own_property (ecma_object_t *obj_p, + ecma_string_t *prop_name_p, + const ecma_property_descriptor_t *prop_desc_p); + +ecma_value_t ecma_ordinary_object_has_property (ecma_object_t *obj_p, ecma_string_t *prop_name_p); + +ecma_value_t ecma_ordinary_object_get (ecma_object_t *obj_p, ecma_string_t *prop_name_p, ecma_value_t base_value); + +ecma_value_t ecma_ordinary_object_set (ecma_object_t *obj_p, + ecma_string_t *prop_name_p, + ecma_value_t name, + ecma_value_t receiver, + bool is_strict); + +ecma_value_t ecma_ordinary_object_delete (ecma_object_t *obj_p, ecma_string_t *prop_name_p, bool is_strict); + +ecma_collection_t *ecma_ordinary_object_own_property_keys (ecma_object_t *obj_p, jerry_property_filter_t filter); + +ecma_value_t ecma_ordinary_object_call (ecma_object_t *obj_p, + ecma_value_t this_value, + const ecma_value_t *arguments_list_p, + uint32_t arguments_list_len); + +ecma_value_t ecma_ordinary_object_construct (ecma_object_t *obj_p, + ecma_object_t *new_target_p, + const ecma_value_t *arguments_list_p, + uint32_t arguments_list_len); + +void ecma_ordinary_object_list_lazy_property_keys (ecma_object_t *obj_p, + ecma_collection_t *prop_names_p, + ecma_property_counter_t *prop_counter_p, + jerry_property_filter_t filter); +void ecma_ordinary_object_delete_lazy_property (ecma_object_t *obj_p, ecma_string_t *prop_name_p); + +/** + * Virtual function table for Ordinary object's internal methods + */ +#define ECMA_ORDINARY_OBJ_VTABLE \ + [ECMA_OBJECT_TYPE_GENERAL] = { ecma_ordinary_object_get_prototype_of, \ + ecma_ordinary_object_set_prototype_of, \ + ecma_ordinary_object_is_extensible, \ + ecma_ordinary_object_prevent_extensions, \ + ecma_ordinary_object_get_own_property, \ + ecma_ordinary_object_define_own_property, \ + ecma_ordinary_object_has_property, \ + ecma_ordinary_object_get, \ + ecma_ordinary_object_set, \ + ecma_ordinary_object_delete, \ + ecma_ordinary_object_own_property_keys, \ + ecma_ordinary_object_call, \ + ecma_ordinary_object_construct, \ + ecma_ordinary_object_list_lazy_property_keys, \ + ecma_ordinary_object_delete_lazy_property } + +/** + * @} + * @} + */ + +#endif /* ECMA_ORDINARY_OBJECT_H */ diff --git a/jerry-core/ecma/operations/ecma-promise-object.c b/jerry-core/ecma/operations/ecma-promise-object.c index 746a841e12..bdaabb6c3d 100644 --- a/jerry-core/ecma/operations/ecma-promise-object.c +++ b/jerry-core/ecma/operations/ecma-promise-object.c @@ -26,6 +26,7 @@ #include "ecma-globals.h" #include "ecma-helpers.h" #include "ecma-jobqueue.h" +#include "ecma-native-function.h" #include "ecma-objects-general.h" #include "ecma-objects.h" @@ -422,7 +423,7 @@ static ecma_object_t * ecma_promise_create_resolving_function (ecma_object_t *promise_p, /**< Promise Object */ ecma_native_handler_id_t id) /**< Callback handler */ { - ecma_object_t *func_obj_p = ecma_op_create_native_handler (id, sizeof (ecma_promise_resolver_t)); + ecma_object_t *func_obj_p = ecma_native_function_create (id, sizeof (ecma_promise_resolver_t)); ecma_promise_resolver_t *resolver_p = (ecma_promise_resolver_t *) func_obj_p; resolver_p->promise = ecma_make_object_value (promise_p); @@ -446,7 +447,7 @@ ecma_promise_run_executor (ecma_object_t *promise_p, /**< Promise Object */ reject_func_p = ecma_promise_create_resolving_function (promise_p, ECMA_NATIVE_HANDLER_PROMISE_REJECT); ecma_value_t argv[] = { ecma_make_object_value (resolve_func_p), ecma_make_object_value (reject_func_p) }; - ecma_value_t result = ecma_op_function_call (ecma_get_object_from_value (executor), this_value, argv, 2); + ecma_value_t result = ecma_internal_method_call (ecma_get_object_from_value (executor), this_value, argv, 2); ecma_deref_object (resolve_func_p); ecma_deref_object (reject_func_p); @@ -653,16 +654,18 @@ ecma_promise_all_or_all_settled_handler_cb (ecma_object_t *function_obj_p, /**< if (promise_type == ECMA_PROMISE_ANY_REJECT) { ecma_value_t error_val = ecma_new_aggregate_error (executor_p->values, ECMA_VALUE_UNDEFINED); - ret = - ecma_op_function_call (ecma_get_object_from_value (capability_p->reject), ECMA_VALUE_UNDEFINED, &error_val, 1); + ret = ecma_internal_method_call (ecma_get_object_from_value (capability_p->reject), + ECMA_VALUE_UNDEFINED, + &error_val, + 1); ecma_free_value (error_val); } else { - ret = ecma_op_function_call (ecma_get_object_from_value (capability_p->resolve), - ECMA_VALUE_UNDEFINED, - &executor_p->values, - 1); + ret = ecma_internal_method_call (ecma_get_object_from_value (capability_p->resolve), + ECMA_VALUE_UNDEFINED, + &executor_p->values, + 1); } } @@ -746,8 +749,8 @@ ecma_promise_new_capability (ecma_value_t constructor, /**< constructor function capability_p->reject = ECMA_VALUE_UNDEFINED; /* 4-5. */ - ecma_object_t *executor_p = ecma_op_create_native_handler (ECMA_NATIVE_HANDLER_PROMISE_CAPABILITY_EXECUTOR, - sizeof (ecma_promise_capability_executor_t)); + ecma_object_t *executor_p = ecma_native_function_create (ECMA_NATIVE_HANDLER_PROMISE_CAPABILITY_EXECUTOR, + sizeof (ecma_promise_capability_executor_t)); /* 6. */ ecma_promise_capability_executor_t *executor_func_p = (ecma_promise_capability_executor_t *) executor_p; @@ -763,7 +766,7 @@ ecma_promise_new_capability (ecma_value_t constructor, /**< constructor function } else { - promise = ecma_op_function_construct (constructor_obj_p, constructor_obj_p, &executor, 1); + promise = ecma_internal_method_construct (constructor_obj_p, constructor_obj_p, &executor, 1); } ecma_deref_object (executor_p); @@ -848,7 +851,8 @@ ecma_promise_reject_or_resolve (ecma_value_t this_arg, /**< "this" argument */ ecma_value_t func = is_resolve ? capability_p->resolve : capability_p->reject; - ecma_value_t call_ret = ecma_op_function_call (ecma_get_object_from_value (func), ECMA_VALUE_UNDEFINED, &value, 1); + ecma_value_t call_ret = + ecma_internal_method_call (ecma_get_object_from_value (func), ECMA_VALUE_UNDEFINED, &value, 1); if (ECMA_IS_VALUE_ERROR (call_ret)) { @@ -971,8 +975,10 @@ ecma_promise_then_catch_finally_helper (ecma_object_t *function_obj_p, /**< func JERRY_ASSERT (ecma_op_is_callable (finally_func_obj->on_finally)); /* 4. */ - ecma_value_t result = - ecma_op_function_call (ecma_get_object_from_value (finally_func_obj->on_finally), ECMA_VALUE_UNDEFINED, NULL, 0); + ecma_value_t result = ecma_internal_method_call (ecma_get_object_from_value (finally_func_obj->on_finally), + ECMA_VALUE_UNDEFINED, + NULL, + 0); if (ECMA_IS_VALUE_ERROR (result)) { @@ -994,7 +1000,7 @@ ecma_promise_then_catch_finally_helper (ecma_object_t *function_obj_p, /**< func /* 8. */ ecma_object_t *value_thunk_func_p; - value_thunk_func_p = ecma_op_create_native_handler (id, sizeof (ecma_promise_value_thunk_t)); + value_thunk_func_p = ecma_native_function_create (id, sizeof (ecma_promise_value_thunk_t)); ecma_promise_value_thunk_t *value_thunk_func_obj = (ecma_promise_value_thunk_t *) value_thunk_func_p; value_thunk_func_obj->value = ecma_copy_value_if_not_object (arg); @@ -1087,7 +1093,7 @@ ecma_promise_finally (ecma_value_t promise, /**< the promise which call 'finally /* 6.a-b */ ecma_object_t *then_finally_obj_p; then_finally_obj_p = - ecma_op_create_native_handler (ECMA_NATIVE_HANDLER_PROMISE_THEN_FINALLY, sizeof (ecma_promise_finally_function_t)); + ecma_native_function_create (ECMA_NATIVE_HANDLER_PROMISE_THEN_FINALLY, sizeof (ecma_promise_finally_function_t)); /* 6.c-d */ ecma_promise_finally_function_t *then_finally_func_obj_p = (ecma_promise_finally_function_t *) then_finally_obj_p; @@ -1097,7 +1103,7 @@ ecma_promise_finally (ecma_value_t promise, /**< the promise which call 'finally /* 6.e-f */ ecma_object_t *catch_finally_obj_p; catch_finally_obj_p = - ecma_op_create_native_handler (ECMA_NATIVE_HANDLER_PROMISE_CATCH_FINALLY, sizeof (ecma_promise_finally_function_t)); + ecma_native_function_create (ECMA_NATIVE_HANDLER_PROMISE_CATCH_FINALLY, sizeof (ecma_promise_finally_function_t)); /* 6.g-h */ ecma_promise_finally_function_t *catch_finally_func_obj = (ecma_promise_finally_function_t *) catch_finally_obj_p; @@ -1214,7 +1220,7 @@ ecma_op_if_abrupt_reject_promise (ecma_value_t *value_p, /**< [in - out] complet ecma_promise_capabality_t *capability_p = (ecma_promise_capabality_t *) capability_obj_p; ecma_value_t call_ret = - ecma_op_function_call (ecma_get_object_from_value (capability_p->reject), ECMA_VALUE_UNDEFINED, &reason, 1); + ecma_internal_method_call (ecma_get_object_from_value (capability_p->reject), ECMA_VALUE_UNDEFINED, &reason, 1); ecma_free_value (reason); if (ECMA_IS_VALUE_ERROR (call_ret)) diff --git a/jerry-core/ecma/operations/ecma-proxy-object.c b/jerry-core/ecma/operations/ecma-proxy-object.c index 35ff2bf00e..a09ba02517 100644 --- a/jerry-core/ecma/operations/ecma-proxy-object.c +++ b/jerry-core/ecma/operations/ecma-proxy-object.c @@ -25,6 +25,7 @@ #include "ecma-gc.h" #include "ecma-globals.h" #include "ecma-helpers.h" +#include "ecma-native-function.h" #include "ecma-objects-general.h" #include "ecma-objects.h" @@ -164,7 +165,7 @@ ecma_proxy_create_revocable (ecma_value_t target, /**< target argument */ /* 3. */ ecma_object_t *func_obj_p; - func_obj_p = ecma_op_create_native_handler (ECMA_NATIVE_HANDLER_PROXY_REVOKE, sizeof (ecma_revocable_proxy_object_t)); + func_obj_p = ecma_native_function_create (ECMA_NATIVE_HANDLER_PROXY_REVOKE, sizeof (ecma_revocable_proxy_object_t)); /* 4. */ ecma_revocable_proxy_object_t *rev_proxy_p = (ecma_revocable_proxy_object_t *) func_obj_p; @@ -198,36 +199,6 @@ ecma_proxy_create_revocable (ecma_value_t target, /**< target argument */ return obj_p; } /* ecma_proxy_create_revocable */ -/** - * Internal find property operation for Proxy object - * - * Note: Returned value must be freed with ecma_free_value. - * - * @return ECMA_VALUE_ERROR - if the operation fails - * ECMA_VALUE_NOT_FOUND - if the property is not found - * value of the property - otherwise - */ -ecma_value_t -ecma_proxy_object_find (ecma_object_t *obj_p, /**< proxy object */ - ecma_string_t *prop_name_p) /**< property name */ -{ - JERRY_ASSERT (ECMA_OBJECT_IS_PROXY (obj_p)); - - ecma_value_t has_result = ecma_proxy_object_has (obj_p, prop_name_p); - - if (ECMA_IS_VALUE_ERROR (has_result)) - { - return has_result; - } - - if (ecma_is_value_false (has_result)) - { - return ECMA_VALUE_NOT_FOUND; - } - - return ecma_proxy_object_get (obj_p, prop_name_p, ecma_make_object_value (obj_p)); -} /* ecma_proxy_object_find */ - /** * Helper method for validate the proxy object * @@ -259,11 +230,18 @@ ecma_validate_proxy_object (ecma_value_t handler, /**< proxy handler */ * @return ECMA_VALUE_ERROR - if the operation fails * ECMA_VALUE_NULL or valid object (prototype) otherwise */ -ecma_value_t +ecma_object_t * ecma_proxy_object_get_prototype_of (ecma_object_t *obj_p) /**< proxy object */ { JERRY_ASSERT (ECMA_OBJECT_IS_PROXY (obj_p)); - ECMA_CHECK_STACK_USAGE (); + +#if (JERRY_STACK_LIMIT != 0) + if (ECMA_STACK_USAGE_LIMIT_REACHED ()) + { + ecma_raise_maximum_callstack_error (); + return ECMA_OBJECT_POINTER_ERROR; + } +#endif /* (JERRY_STACK_LIMIT != 0) */ ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) obj_p; @@ -276,7 +254,7 @@ ecma_proxy_object_get_prototype_of (ecma_object_t *obj_p) /**< proxy object */ /* 6. */ if (ECMA_IS_VALUE_ERROR (trap)) { - return trap; + return ECMA_OBJECT_POINTER_ERROR; } ecma_value_t target = proxy_obj_p->target; @@ -285,7 +263,7 @@ ecma_proxy_object_get_prototype_of (ecma_object_t *obj_p) /**< proxy object */ /* 7. */ if (ecma_is_value_undefined (trap)) { - ecma_value_t result = ecma_builtin_object_object_get_prototype_of (target_obj_p); + ecma_object_t *result = ecma_internal_method_get_prototype_of (target_obj_p); JERRY_BLOCK_TAIL_CALL_OPTIMIZATION (); return result; } @@ -293,69 +271,79 @@ ecma_proxy_object_get_prototype_of (ecma_object_t *obj_p) /**< proxy object */ ecma_object_t *func_obj_p = ecma_get_object_from_value (trap); /* 8. */ - ecma_value_t handler_proto = ecma_op_function_call (func_obj_p, handler, &target, 1); + ecma_value_t handler_proto = ecma_internal_method_call (func_obj_p, handler, &target, 1); ecma_deref_object (func_obj_p); /* 9. */ if (ECMA_IS_VALUE_ERROR (handler_proto)) { - return handler_proto; + return ECMA_OBJECT_POINTER_ERROR; } /* 10. */ if (!ecma_is_value_object (handler_proto) && !ecma_is_value_null (handler_proto)) { ecma_free_value (handler_proto); + ecma_raise_type_error (ECMA_ERR_TRAP_RETURNED_NEITHER_OBJECT_NOR_NULL); + return ECMA_OBJECT_POINTER_ERROR; + } - return ecma_raise_type_error (ECMA_ERR_TRAP_RETURNED_NEITHER_OBJECT_NOR_NULL); + ecma_object_t *handler_proto_obj; + + if (ecma_is_value_null (handler_proto)) + { + handler_proto_obj = NULL; + } + else + { + handler_proto_obj = ecma_get_object_from_value (handler_proto); } if (obj_p->u2.prototype_cp & JERRY_PROXY_SKIP_RESULT_VALIDATION) { - return handler_proto; + return handler_proto_obj; } /* 11. */ - ecma_value_t extensible_target = ecma_builtin_object_object_is_extensible (target_obj_p); + ecma_value_t extensible_target = ecma_internal_method_is_extensible (target_obj_p); /* 12. */ if (ECMA_IS_VALUE_ERROR (extensible_target)) { ecma_free_value (handler_proto); - return extensible_target; + return ECMA_OBJECT_POINTER_ERROR; } /* 13. */ if (ecma_is_value_true (extensible_target)) { - return handler_proto; + return handler_proto_obj; } /* 14. */ - ecma_value_t target_proto = ecma_builtin_object_object_get_prototype_of (target_obj_p); + ecma_object_t *target_proto = ecma_internal_method_get_prototype_of (target_obj_p); /* 15. */ - if (ECMA_IS_VALUE_ERROR (target_proto)) + if (JERRY_UNLIKELY (target_proto == ECMA_OBJECT_POINTER_ERROR)) { return target_proto; } - ecma_value_t ret_value = handler_proto; - /* 16. */ - if (handler_proto != target_proto) + if (handler_proto_obj != target_proto) { ecma_free_value (handler_proto); - - ret_value = ecma_raise_type_error (ECMA_ERR_TARGET_NOT_EXTENSIBLE_NOT_RETURNED_ITS_PROTOTYPE); + ecma_deref_object (target_proto); + ecma_raise_type_error (ECMA_ERR_TARGET_NOT_EXTENSIBLE_NOT_RETURNED_ITS_PROTOTYPE); + return ECMA_OBJECT_POINTER_ERROR; } - ecma_free_value (target_proto); + ecma_deref_object (target_proto); /* 17. */ - return ret_value; + return handler_proto_obj; } /* ecma_proxy_object_get_prototype_of */ /** @@ -400,14 +388,7 @@ ecma_proxy_object_set_prototype_of (ecma_object_t *obj_p, /**< proxy object */ /* 8. */ if (ecma_is_value_undefined (trap)) { - if (ECMA_OBJECT_IS_PROXY (target_obj_p)) - { - ecma_value_t result = ecma_proxy_object_set_prototype_of (target_obj_p, proto); - JERRY_BLOCK_TAIL_CALL_OPTIMIZATION (); - return result; - } - - ecma_value_t result = ecma_op_ordinary_object_set_prototype_of (target_obj_p, proto); + ecma_value_t result = ecma_internal_method_set_prototype_of (target_obj_p, proto); JERRY_BLOCK_TAIL_CALL_OPTIMIZATION (); return result; } @@ -416,7 +397,7 @@ ecma_proxy_object_set_prototype_of (ecma_object_t *obj_p, /**< proxy object */ ecma_value_t args[] = { target, proto }; /* 9. */ - ecma_value_t trap_result = ecma_op_function_call (func_obj_p, handler, args, 2); + ecma_value_t trap_result = ecma_internal_method_call (func_obj_p, handler, args, 2); ecma_deref_object (func_obj_p); @@ -442,7 +423,7 @@ ecma_proxy_object_set_prototype_of (ecma_object_t *obj_p, /**< proxy object */ } /* 11. */ - ecma_value_t extensible_target = ecma_builtin_object_object_is_extensible (target_obj_p); + ecma_value_t extensible_target = ecma_internal_method_is_extensible (target_obj_p); /* 12. */ if (ECMA_IS_VALUE_ERROR (extensible_target)) @@ -516,7 +497,7 @@ ecma_proxy_object_is_extensible (ecma_object_t *obj_p) /**< proxy object */ /* 7. */ if (ecma_is_value_undefined (trap)) { - ecma_value_t result = ecma_builtin_object_object_is_extensible (target_obj_p); + ecma_value_t result = ecma_internal_method_is_extensible (target_obj_p); JERRY_BLOCK_TAIL_CALL_OPTIMIZATION (); return result; } @@ -524,7 +505,7 @@ ecma_proxy_object_is_extensible (ecma_object_t *obj_p) /**< proxy object */ ecma_object_t *func_obj_p = ecma_get_object_from_value (trap); /* 8. */ - ecma_value_t trap_result = ecma_op_function_call (func_obj_p, handler, &target, 1); + ecma_value_t trap_result = ecma_internal_method_call (func_obj_p, handler, &target, 1); ecma_deref_object (func_obj_p); @@ -534,32 +515,21 @@ ecma_proxy_object_is_extensible (ecma_object_t *obj_p) /**< proxy object */ return trap_result; } - bool boolean_trap_result = ecma_op_to_boolean (trap_result); + ecma_value_t boolean_trap_result = ecma_make_boolean_value (ecma_op_to_boolean (trap_result)); ecma_free_value (trap_result); if (obj_p->u2.prototype_cp & JERRY_PROXY_SKIP_RESULT_VALIDATION) { - return ecma_make_boolean_value (boolean_trap_result); + return boolean_trap_result; } - bool target_result; + ecma_value_t target_result = ecma_internal_method_is_extensible (target_obj_p); /* 10. */ - if (ECMA_OBJECT_IS_PROXY (target_obj_p)) + if (ECMA_IS_VALUE_ERROR (target_result)) { - ecma_value_t proxy_is_ext = ecma_proxy_object_is_extensible (target_obj_p); - - if (ECMA_IS_VALUE_ERROR (proxy_is_ext)) - { - return proxy_is_ext; - } - - target_result = ecma_is_value_true (proxy_is_ext); - } - else - { - target_result = ecma_op_ordinary_object_is_extensible (target_obj_p); + return target_result; } /* 12. */ @@ -568,7 +538,7 @@ ecma_proxy_object_is_extensible (ecma_object_t *obj_p) /**< proxy object */ return ecma_raise_type_error (ECMA_ERR_TRAP_RESULT_NOT_REFLECT_TARGET_EXTENSIBILITY); } - return ecma_make_boolean_value (boolean_trap_result); + return boolean_trap_result; } /* ecma_proxy_object_is_extensible */ /** @@ -623,7 +593,7 @@ ecma_proxy_object_prevent_extensions (ecma_object_t *obj_p) /**< proxy object */ ecma_object_t *func_obj_p = ecma_get_object_from_value (trap); /* 8. */ - ecma_value_t trap_result = ecma_op_function_call (func_obj_p, handler, &target, 1); + ecma_value_t trap_result = ecma_internal_method_call (func_obj_p, handler, &target, 1); ecma_deref_object (func_obj_p); @@ -640,7 +610,7 @@ ecma_proxy_object_prevent_extensions (ecma_object_t *obj_p) /**< proxy object */ /* 10. */ if (boolean_trap_result && !(obj_p->u2.prototype_cp & JERRY_PROXY_SKIP_RESULT_VALIDATION)) { - ecma_value_t target_is_ext = ecma_builtin_object_object_is_extensible (target_obj_p); + ecma_value_t target_is_ext = ecma_internal_method_is_extensible (target_obj_p); if (ECMA_IS_VALUE_ERROR (target_is_ext)) { @@ -669,13 +639,20 @@ ecma_proxy_object_prevent_extensions (ecma_object_t *obj_p) /**< proxy object */ * @return ECMA_VALUE_ERROR - if the operation fails * ECMA_VALUE_{TRUE_FALSE} - depends on whether object has property with the given name */ -ecma_value_t -ecma_proxy_object_get_own_property_descriptor (ecma_object_t *obj_p, /**< proxy object */ - ecma_string_t *prop_name_p, /**< property name */ - ecma_property_descriptor_t *prop_desc_p) /**< [out] property - * descriptor */ +ecma_property_descriptor_t +ecma_proxy_object_get_own_property (ecma_object_t *obj_p, /**< the object */ + ecma_string_t *prop_name_p) /**< property name */ { - ECMA_CHECK_STACK_USAGE (); + ecma_property_descriptor_t prop_desc = ecma_make_empty_define_property_descriptor (); + +#if (JERRY_STACK_LIMIT != 0) + if (ECMA_STACK_USAGE_LIMIT_REACHED ()) + { + ecma_raise_maximum_callstack_error (); + prop_desc.flags = ECMA_PROP_DESC_ERROR; + return prop_desc; + } +#endif /* (JERRY_STACK_LIMIT != 0) */ ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) obj_p; @@ -690,7 +667,8 @@ ecma_proxy_object_get_own_property_descriptor (ecma_object_t *obj_p, /**< proxy /* 7. */ if (ECMA_IS_VALUE_ERROR (trap)) { - return trap; + prop_desc.flags = ECMA_PROP_DESC_ERROR; + return prop_desc; } ecma_object_t *target_obj_p = ecma_get_object_from_value (target); @@ -698,7 +676,7 @@ ecma_proxy_object_get_own_property_descriptor (ecma_object_t *obj_p, /**< proxy /* 8. */ if (ecma_is_value_undefined (trap)) { - ecma_value_t result = ecma_op_object_get_own_property_descriptor (target_obj_p, prop_name_p, prop_desc_p); + ecma_property_descriptor_t result = ecma_internal_method_get_own_property (target_obj_p, prop_name_p); JERRY_BLOCK_TAIL_CALL_OPTIMIZATION (); return result; } @@ -708,75 +686,90 @@ ecma_proxy_object_get_own_property_descriptor (ecma_object_t *obj_p, /**< proxy ecma_value_t args[] = { target, prop_value }; /* 9. */ - ecma_value_t trap_result = ecma_op_function_call (func_obj_p, handler, args, 2); + ecma_value_t trap_result = ecma_internal_method_call (func_obj_p, handler, args, 2); ecma_deref_object (func_obj_p); /* 10. */ if (ECMA_IS_VALUE_ERROR (trap_result)) { - return trap_result; + prop_desc.flags = ECMA_PROP_DESC_ERROR; + return prop_desc; } /* 11. */ if (!ecma_is_value_object (trap_result) && !ecma_is_value_undefined (trap_result)) { ecma_free_value (trap_result); - return ecma_raise_type_error (ECMA_ERR_TRAP_IS_NEITHER_AN_OBJECT_NOR_UNDEFINED); + ecma_raise_type_error (ECMA_ERR_TRAP_IS_NEITHER_AN_OBJECT_NOR_UNDEFINED); + prop_desc.flags = ECMA_PROP_DESC_ERROR; + return prop_desc; } if (obj_p->u2.prototype_cp & JERRY_PROXY_SKIP_RESULT_VALIDATION) { if (ecma_is_value_undefined (trap_result)) { - return ECMA_VALUE_FALSE; + prop_desc.flags |= ECMA_PROP_DESC_FOUND; + return prop_desc; } - ecma_value_t result_val = ecma_op_to_property_descriptor (trap_result, prop_desc_p); + ecma_value_t result_val = ecma_op_to_property_descriptor (trap_result, &prop_desc); ecma_free_value (trap_result); if (ECMA_IS_VALUE_ERROR (result_val)) { - return result_val; + ecma_free_define_property_descriptor (&prop_desc); + prop_desc.flags = ECMA_PROP_DESC_ERROR; + } + else + { + ecma_op_to_complete_property_descriptor (&prop_desc); + prop_desc.flags |= ECMA_PROP_DESC_FOUND; } - ecma_op_to_complete_property_descriptor (prop_desc_p); - return ECMA_VALUE_TRUE; + return prop_desc; } /* 12. */ - ecma_property_descriptor_t target_desc; - ecma_value_t target_status = ecma_op_object_get_own_property_descriptor (target_obj_p, prop_name_p, &target_desc); + ecma_property_descriptor_t target_prop_desc = ecma_internal_method_get_own_property (target_obj_p, prop_name_p); /* 13. */ - if (ECMA_IS_VALUE_ERROR (target_status)) + if (ecma_property_descriptor_error (&target_prop_desc)) { ecma_free_value (trap_result); - return target_status; + ecma_free_property_descriptor (&target_prop_desc); + prop_desc.flags = ECMA_PROP_DESC_ERROR; + return prop_desc; } /* 14. */ if (ecma_is_value_undefined (trap_result)) { /* .a */ - if (ecma_is_value_false (target_status)) + if (!ecma_property_descriptor_found (&target_prop_desc)) { - return ECMA_VALUE_FALSE; + ecma_free_property_descriptor (&target_prop_desc); + return prop_desc; } + /* .b */ - if (!(target_desc.flags & JERRY_PROP_IS_CONFIGURABLE)) + if (!ecma_property_descriptor_is_configurable (&target_prop_desc)) { - ecma_free_property_descriptor (&target_desc); - return ecma_raise_type_error (ECMA_ERR_GIVEN_PROPERTY_IS_A_NON_CONFIGURABLE); + ecma_raise_type_error (ECMA_ERR_GIVEN_PROPERTY_IS_A_NON_CONFIGURABLE); + ecma_free_property_descriptor (&target_prop_desc); + prop_desc.flags = ECMA_PROP_DESC_ERROR; + return prop_desc; } /* .c */ - ecma_free_property_descriptor (&target_desc); - ecma_value_t extensible_target = ecma_builtin_object_object_is_extensible (target_obj_p); + ecma_value_t extensible_target = ecma_internal_method_is_extensible (target_obj_p); /* .d */ if (ECMA_IS_VALUE_ERROR (extensible_target)) { - return extensible_target; + ecma_free_property_descriptor (&target_prop_desc); + prop_desc.flags = ECMA_PROP_DESC_ERROR; + return prop_desc; } /* .e */ @@ -785,81 +778,83 @@ ecma_proxy_object_get_own_property_descriptor (ecma_object_t *obj_p, /**< proxy /* .f */ if (ecma_is_value_false (extensible_target)) { - return ecma_raise_type_error (ECMA_ERR_TARGET_NOT_EXTENSIBLE); + ecma_raise_type_error (ECMA_ERR_TARGET_NOT_EXTENSIBLE); + ecma_free_property_descriptor (&target_prop_desc); + prop_desc.flags = ECMA_PROP_DESC_ERROR; + return prop_desc; } + ecma_free_property_descriptor (&target_prop_desc); + /* .g */ - return ECMA_VALUE_FALSE; + return prop_desc; } /* 15. */ - ecma_value_t extensible_target = ecma_builtin_object_object_is_extensible (target_obj_p); + ecma_value_t extensible_target = ecma_internal_method_is_extensible (target_obj_p); /* 16. */ if (ECMA_IS_VALUE_ERROR (extensible_target)) { - if (ecma_is_value_true (target_status)) - { - ecma_free_property_descriptor (&target_desc); - } ecma_free_value (trap_result); - return extensible_target; + ecma_free_property_descriptor (&target_prop_desc); + prop_desc.flags = ECMA_PROP_DESC_ERROR; + return prop_desc; } /* 17, 19 */ - ecma_value_t result_val = ecma_op_to_property_descriptor (trap_result, prop_desc_p); - - ecma_op_to_complete_property_descriptor (prop_desc_p); + ecma_value_t result_val = ecma_op_to_property_descriptor (trap_result, &prop_desc); + ecma_op_to_complete_property_descriptor (&prop_desc); ecma_free_value (trap_result); /* 18. */ if (ECMA_IS_VALUE_ERROR (result_val)) { - if (ecma_is_value_true (target_status)) - { - ecma_free_property_descriptor (&target_desc); - } - return result_val; + ecma_free_define_property_descriptor (&prop_desc); + ecma_free_property_descriptor (&target_prop_desc); + prop_desc.flags = ECMA_PROP_DESC_ERROR; + return prop_desc; } /* 20. */ bool is_extensible = ecma_is_value_true (extensible_target); - bool is_valid = ecma_op_is_compatible_property_descriptor (prop_desc_p, - (ecma_is_value_true (target_status) ? &target_desc : NULL), - is_extensible); - - bool target_has_desc = ecma_is_value_true (target_status); - bool target_is_writable = (target_desc.flags & JERRY_PROP_IS_WRITABLE); - bool target_is_configurable = false; - - if (target_has_desc) - { - target_is_configurable = ((target_desc.flags & JERRY_PROP_IS_CONFIGURABLE) != 0); - ecma_free_property_descriptor (&target_desc); - } + bool is_valid = + ecma_op_validate_and_apply_property_descriptor (NULL, NULL, &prop_desc, &target_prop_desc, is_extensible); /* 21. */ if (!is_valid) { - ecma_free_property_descriptor (prop_desc_p); - return ecma_raise_type_error (ECMA_ERR_THE_TWO_DESCRIPTORS_ARE_INCOMPATIBLE); + ecma_raise_type_error (ECMA_ERR_THE_TWO_DESCRIPTORS_ARE_INCOMPATIBLE); + ecma_free_property_descriptor (&target_prop_desc); + ecma_free_define_property_descriptor (&prop_desc); + prop_desc.flags = ECMA_PROP_DESC_ERROR; + return prop_desc; } /* 22. */ - else if (!(prop_desc_p->flags & JERRY_PROP_IS_CONFIGURABLE)) + if (!(prop_desc.flags & JERRY_PROP_IS_CONFIGURABLE)) { const uint16_t mask = (JERRY_PROP_IS_WRITABLE_DEFINED | JERRY_PROP_IS_WRITABLE); - if (!target_has_desc || target_is_configurable - || ((prop_desc_p->flags & mask) == JERRY_PROP_IS_WRITABLE_DEFINED && target_is_writable)) + if (!ecma_property_descriptor_found (&target_prop_desc) + || ecma_property_descriptor_is_configurable (&target_prop_desc) + || ((prop_desc.flags & mask) == JERRY_PROP_IS_WRITABLE_DEFINED + && ecma_property_descriptor_is_writable (&target_prop_desc))) { - ecma_free_property_descriptor (prop_desc_p); - return ecma_raise_type_error (ECMA_ERR_THE_TWO_DESCRIPTORS_ARE_INCOMPATIBLE); + ecma_free_property_descriptor (&target_prop_desc); + ecma_free_define_property_descriptor (&prop_desc); + ecma_raise_type_error (ECMA_ERR_THE_TWO_DESCRIPTORS_ARE_INCOMPATIBLE); + prop_desc.flags = ECMA_PROP_DESC_ERROR; + return prop_desc; } } - return ECMA_VALUE_TRUE; -} /* ecma_proxy_object_get_own_property_descriptor */ + + prop_desc.flags |= ECMA_PROP_DESC_FOUND; + ecma_free_property_descriptor (&target_prop_desc); + + return prop_desc; +} /* ecma_proxy_object_get_own_property */ /** * The Proxy object [[DefineOwnProperty]] internal routine @@ -900,7 +895,7 @@ ecma_proxy_object_define_own_property (ecma_object_t *obj_p, /**< proxy object * /* 8. */ if (ecma_is_value_undefined (trap)) { - ecma_value_t result = ecma_op_object_define_own_property (target_obj_p, prop_name_p, prop_desc_p); + ecma_value_t result = ecma_internal_method_define_own_property (target_obj_p, prop_name_p, prop_desc_p); JERRY_BLOCK_TAIL_CALL_OPTIMIZATION (); return result; } @@ -914,7 +909,7 @@ ecma_proxy_object_define_own_property (ecma_object_t *obj_p, /**< proxy object * ecma_value_t args[] = { target, prop_value, desc_obj_value }; /* 10. */ - ecma_value_t trap_result = ecma_op_function_call (func_obj_p, handler, args, 3); + ecma_value_t trap_result = ecma_internal_method_call (func_obj_p, handler, args, 3); ecma_deref_object (func_obj_p); ecma_deref_object (desc_obj); @@ -932,7 +927,7 @@ ecma_proxy_object_define_own_property (ecma_object_t *obj_p, /**< proxy object * /* 12. */ if (!boolean_trap_result) { - return ECMA_VALUE_FALSE; + return ecma_raise_property_redefinition (prop_name_p, prop_desc_p->flags); } if (obj_p->u2.prototype_cp & JERRY_PROXY_SKIP_RESULT_VALIDATION) @@ -941,31 +936,24 @@ ecma_proxy_object_define_own_property (ecma_object_t *obj_p, /**< proxy object * } /* 13. */ - ecma_property_descriptor_t target_desc; - - ecma_value_t status = ecma_op_object_get_own_property_descriptor (target_obj_p, prop_name_p, &target_desc); + ecma_property_descriptor_t target_prop_desc = ecma_internal_method_get_own_property (target_obj_p, prop_name_p); /* 14. */ - if (ECMA_IS_VALUE_ERROR (status)) + if (ecma_property_descriptor_error (&target_prop_desc)) { - return status; + ecma_free_property_descriptor (&target_prop_desc); + return ECMA_VALUE_ERROR; } - bool target_prop_found = ecma_is_value_true (status); - /* 15. */ - ecma_value_t extensible_target = ecma_builtin_object_object_is_extensible (target_obj_p); + ecma_value_t extensible_target = ecma_internal_method_is_extensible (target_obj_p); bool is_target_ext = ecma_is_value_true (extensible_target); /* 16. */ if (ECMA_IS_VALUE_ERROR (extensible_target)) { - if (target_prop_found) - { - ecma_free_property_descriptor (&target_desc); - } - + ecma_free_property_descriptor (&target_prop_desc); return extensible_target; } @@ -974,15 +962,17 @@ ecma_proxy_object_define_own_property (ecma_object_t *obj_p, /**< proxy object * ((prop_desc_p->flags & JERRY_PROP_IS_CONFIGURABLE_DEFINED) && !(prop_desc_p->flags & JERRY_PROP_IS_CONFIGURABLE)); /* 19. */ - if (!target_prop_found) + if (!ecma_property_descriptor_found (&target_prop_desc)) { if (!is_target_ext) { + ecma_free_property_descriptor (&target_prop_desc); return ecma_raise_type_error (ECMA_ERR_TRAP_TRUISH_ADDING_PROPERTY_NON_EXTENSIBLE_TARGET); } if (setting_config_false) { + ecma_free_property_descriptor (&target_prop_desc); return ecma_raise_type_error (ECMA_ERR_TRAP_TRUISH_DEFINING_NON_EXISTENT_PROPERTY); } } @@ -991,32 +981,34 @@ ecma_proxy_object_define_own_property (ecma_object_t *obj_p, /**< proxy object * { ecma_value_t ret_value = ECMA_VALUE_EMPTY; - if (!ecma_op_is_compatible_property_descriptor (prop_desc_p, &target_desc, is_target_ext)) + if (!ecma_op_validate_and_apply_property_descriptor (NULL, NULL, prop_desc_p, &target_prop_desc, is_target_ext)) { ret_value = ecma_raise_type_error (ECMA_ERR_TRAP_TRUISH_ADD_PROPERTY_INCOMPATIBLE_OTHER_PROP); } - else if (setting_config_false && (target_desc.flags & JERRY_PROP_IS_CONFIGURABLE)) + else if (setting_config_false && ecma_property_descriptor_is_configurable (&target_prop_desc)) { ret_value = ecma_raise_type_error (ECMA_ERR_TRAP_TRUISH_DEFINING_NON_EXISTENT_PROPERTY); } /* ES11: 16.c */ - else if ((target_desc.flags & (JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_IS_WRITABLE_DEFINED)) != 0 + else if (ecma_property_descriptor_is_data_descriptor (&target_prop_desc) && (prop_desc_p->flags & (JERRY_PROP_IS_WRITABLE_DEFINED | JERRY_PROP_IS_WRITABLE)) == JERRY_PROP_IS_WRITABLE_DEFINED - && (target_desc.flags & (JERRY_PROP_IS_WRITABLE | JERRY_PROP_IS_CONFIGURABLE)) == JERRY_PROP_IS_WRITABLE) + && !ecma_property_descriptor_is_configurable (&target_prop_desc) + && ecma_property_descriptor_is_writable (&target_prop_desc)) { ret_value = ecma_raise_type_error (ECMA_ERR_TRAP_TRUISH_DEFINING_NON_EXISTENT_PROPERTY); } - ecma_free_property_descriptor (&target_desc); - if (ECMA_IS_VALUE_ERROR (ret_value)) { + ecma_free_property_descriptor (&target_prop_desc); return ret_value; } } + ecma_free_property_descriptor (&target_prop_desc); + return ECMA_VALUE_TRUE; } /* ecma_proxy_object_define_own_property */ @@ -1032,8 +1024,8 @@ ecma_proxy_object_define_own_property (ecma_object_t *obj_p, /**< proxy object * * ECMA_VALUE_{TRUE_FALSE} - depends on whether the property is found */ ecma_value_t -ecma_proxy_object_has (ecma_object_t *obj_p, /**< proxy object */ - ecma_string_t *prop_name_p) /**< property name */ +ecma_proxy_object_has_property (ecma_object_t *obj_p, /**< proxy object */ + ecma_string_t *prop_name_p) /**< property name */ { JERRY_ASSERT (ECMA_OBJECT_IS_PROXY (obj_p)); ECMA_CHECK_STACK_USAGE (); @@ -1058,7 +1050,7 @@ ecma_proxy_object_has (ecma_object_t *obj_p, /**< proxy object */ /* 8. */ if (ecma_is_value_undefined (trap)) { - ecma_value_t result = ecma_op_object_has_property (target_obj_p, prop_name_p); + ecma_value_t result = ecma_internal_method_has_property (target_obj_p, prop_name_p); JERRY_BLOCK_TAIL_CALL_OPTIMIZATION (); return result; } @@ -1068,7 +1060,7 @@ ecma_proxy_object_has (ecma_object_t *obj_p, /**< proxy object */ ecma_value_t args[] = { target, prop_value }; /* 9. */ - ecma_value_t trap_result = ecma_op_function_call (func_obj_p, handler, args, 2); + ecma_value_t trap_result = ecma_internal_method_call (func_obj_p, handler, args, 2); ecma_deref_object (func_obj_p); @@ -1085,27 +1077,26 @@ ecma_proxy_object_has (ecma_object_t *obj_p, /**< proxy object */ /* 11. */ if (!boolean_trap_result && !(obj_p->u2.prototype_cp & JERRY_PROXY_SKIP_RESULT_VALIDATION)) { - ecma_property_descriptor_t target_desc; - - ecma_value_t status = ecma_op_object_get_own_property_descriptor (target_obj_p, prop_name_p, &target_desc); + ecma_property_descriptor_t prop_desc = ecma_internal_method_get_own_property (target_obj_p, prop_name_p); - if (ECMA_IS_VALUE_ERROR (status)) + if (ecma_property_descriptor_error (&prop_desc)) { - return status; + ecma_free_property_descriptor (&prop_desc); + return ECMA_VALUE_ERROR; } - if (ecma_is_value_true (status)) + if (ecma_property_descriptor_found (&prop_desc)) { - bool prop_is_configurable = target_desc.flags & JERRY_PROP_IS_CONFIGURABLE; + bool prop_is_configurable = ecma_property_descriptor_is_configurable (&prop_desc); - ecma_free_property_descriptor (&target_desc); + ecma_free_property_descriptor (&prop_desc); if (!prop_is_configurable) { return ecma_raise_type_error (ECMA_ERR_TRAP_FALSISH_PROPERTY_NON_CONFIGURABLE); } - ecma_value_t extensible_target = ecma_builtin_object_object_is_extensible (target_obj_p); + ecma_value_t extensible_target = ecma_internal_method_is_extensible (target_obj_p); if (ECMA_IS_VALUE_ERROR (extensible_target)) { @@ -1117,6 +1108,10 @@ ecma_proxy_object_has (ecma_object_t *obj_p, /**< proxy object */ return ecma_raise_type_error (ECMA_ERR_TRAP_FALSISH_PROPERTY_TARGET_NOT_EXTENSIBLE); } } + else + { + ecma_free_property_descriptor (&prop_desc); + } } /* 12. */ @@ -1160,7 +1155,7 @@ ecma_proxy_object_get (ecma_object_t *obj_p, /**< proxy object */ if (ecma_is_value_undefined (trap)) { ecma_object_t *target_obj_p = ecma_get_object_from_value (proxy_obj_p->target); - ecma_value_t result = ecma_op_object_get_with_receiver (target_obj_p, prop_name_p, receiver); + ecma_value_t result = ecma_internal_method_get (target_obj_p, prop_name_p, receiver); JERRY_BLOCK_TAIL_CALL_OPTIMIZATION (); return result; } @@ -1170,7 +1165,7 @@ ecma_proxy_object_get (ecma_object_t *obj_p, /**< proxy object */ ecma_value_t args[] = { proxy_obj_p->target, prop_value, receiver }; /* 9. */ - ecma_value_t trap_result = ecma_op_function_call (func_obj_p, handler, args, 3); + ecma_value_t trap_result = ecma_internal_method_call (func_obj_p, handler, args, 3); ecma_deref_object (func_obj_p); @@ -1180,44 +1175,51 @@ ecma_proxy_object_get (ecma_object_t *obj_p, /**< proxy object */ return trap_result; } + if (!ecma_is_value_object (proxy_obj_p->target)) + { + return trap_result; + } + /* 11. */ - ecma_property_descriptor_t target_desc; - ecma_value_t status = ecma_op_get_own_property_descriptor (proxy_obj_p->target, prop_name_p, &target_desc); + ecma_property_descriptor_t prop_desc = + ecma_internal_method_get_own_property (ecma_get_object_from_value (proxy_obj_p->target), prop_name_p); /* 12. */ - if (ECMA_IS_VALUE_ERROR (status)) + if (ecma_property_descriptor_error (&prop_desc)) { ecma_free_value (trap_result); - return status; + ecma_free_property_descriptor (&prop_desc); + return ECMA_VALUE_ERROR; } /* 13. */ - if (ecma_is_value_true (status)) + if (ecma_property_descriptor_found (&prop_desc)) { ecma_value_t ret_value = ECMA_VALUE_EMPTY; - if ((target_desc.flags & JERRY_PROP_IS_VALUE_DEFINED) && !(target_desc.flags & JERRY_PROP_IS_CONFIGURABLE) - && !(target_desc.flags & JERRY_PROP_IS_WRITABLE) && !ecma_op_same_value (trap_result, target_desc.value)) + if (ecma_property_descriptor_is_data_descriptor (&prop_desc) + && !ecma_property_descriptor_is_configurable (&prop_desc) && !ecma_property_descriptor_is_writable (&prop_desc) + && !ecma_op_same_value (trap_result, ecma_property_descriptor_value (&prop_desc))) { ret_value = ecma_raise_type_error (ECMA_ERR_INCORRECT_RETURN_PROXY_GET_TRAP); } - else if (!(target_desc.flags & JERRY_PROP_IS_CONFIGURABLE) - && (target_desc.flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED)) - && target_desc.get_p == NULL && !ecma_is_value_undefined (trap_result)) + else if (!ecma_property_descriptor_is_configurable (&prop_desc) + && !ecma_property_descriptor_is_data_descriptor (&prop_desc) + && ecma_property_descriptor_accessor_getter (&prop_desc) == NULL && !ecma_is_value_undefined (trap_result)) { ret_value = ecma_raise_type_error (ECMA_ERR_PROXY_PROPERTY_NOT_CONFIGURABLE_NOT_HAVE_GETTER); } - ecma_free_property_descriptor (&target_desc); - if (ECMA_IS_VALUE_ERROR (ret_value)) { ecma_free_value (trap_result); - + ecma_free_property_descriptor (&prop_desc); return ret_value; } } + ecma_free_property_descriptor (&prop_desc); + /* 14. */ return trap_result; } /* ecma_proxy_object_get */ @@ -1263,7 +1265,7 @@ ecma_proxy_object_set (ecma_object_t *obj_p, /**< proxy object */ /* 8. */ if (ecma_is_value_undefined (trap)) { - ecma_value_t result = ecma_op_object_put_with_receiver (target_obj_p, prop_name_p, value, receiver, is_strict); + ecma_value_t result = ecma_internal_method_set (target_obj_p, prop_name_p, value, receiver, is_strict); JERRY_BLOCK_TAIL_CALL_OPTIMIZATION (); return result; } @@ -1273,7 +1275,7 @@ ecma_proxy_object_set (ecma_object_t *obj_p, /**< proxy object */ ecma_value_t args[] = { target, prop_name_value, value, receiver }; /* 9. */ - ecma_value_t trap_result = ecma_op_function_call (func_obj_p, handler, args, 4); + ecma_value_t trap_result = ecma_internal_method_call (func_obj_p, handler, args, 4); ecma_deref_object (func_obj_p); @@ -1304,41 +1306,41 @@ ecma_proxy_object_set (ecma_object_t *obj_p, /**< proxy object */ } /* 12. */ - ecma_property_descriptor_t target_desc; - - ecma_value_t status = ecma_op_object_get_own_property_descriptor (target_obj_p, prop_name_p, &target_desc); + ecma_property_descriptor_t prop_desc = ecma_internal_method_get_own_property (target_obj_p, prop_name_p); /* 13. */ - if (ECMA_IS_VALUE_ERROR (status)) + if (ecma_property_descriptor_error (&prop_desc)) { - return status; + ecma_free_property_descriptor (&prop_desc); + return ECMA_VALUE_ERROR; } /* 14. */ - if (ecma_is_value_true (status)) + if (ecma_property_descriptor_found (&prop_desc)) { ecma_value_t ret_value = ECMA_VALUE_EMPTY; - if ((target_desc.flags & JERRY_PROP_IS_VALUE_DEFINED) && !(target_desc.flags & JERRY_PROP_IS_CONFIGURABLE) - && !(target_desc.flags & JERRY_PROP_IS_WRITABLE) && !ecma_op_same_value (value, target_desc.value)) + if (ecma_property_descriptor_is_data_descriptor (&prop_desc) + && !ecma_property_descriptor_is_configurable (&prop_desc) && !ecma_property_descriptor_is_writable (&prop_desc) + && !ecma_op_same_value (value, ecma_property_descriptor_value (&prop_desc))) { ret_value = ecma_raise_type_error (ECMA_ERR_INCORRECT_RETURN_PROXY_SET_TRAP); } - else if (!(target_desc.flags & JERRY_PROP_IS_CONFIGURABLE) - && (target_desc.flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED)) - && target_desc.set_p == NULL) + else if (!ecma_property_descriptor_is_configurable (&prop_desc) + && !ecma_property_descriptor_is_data_descriptor (&prop_desc) + && ecma_property_descriptor_accessor_setter (&prop_desc) == NULL) { ret_value = ecma_raise_type_error (ECMA_ERR_TARGET_PROPERTY_CONFIGURE_ACCESSOR_WITHOUT_SETTER); } - ecma_free_property_descriptor (&target_desc); - if (ECMA_IS_VALUE_ERROR (ret_value)) { + ecma_free_property_descriptor (&prop_desc); return ret_value; } } + ecma_free_property_descriptor (&prop_desc); /* 15. */ return ECMA_VALUE_TRUE; } /* ecma_proxy_object_set */ @@ -1359,6 +1361,8 @@ ecma_proxy_object_delete_property (ecma_object_t *obj_p, /**< proxy object */ ecma_string_t *prop_name_p, /**< property name */ bool is_strict) /**< delete in strict mode? */ { + JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p)); + JERRY_ASSERT (prop_name_p != NULL); JERRY_ASSERT (ECMA_OBJECT_IS_PROXY (obj_p)); ECMA_CHECK_STACK_USAGE (); @@ -1382,7 +1386,7 @@ ecma_proxy_object_delete_property (ecma_object_t *obj_p, /**< proxy object */ /* 8. */ if (ecma_is_value_undefined (trap)) { - ecma_value_t result = ecma_op_object_delete (target_obj_p, prop_name_p, is_strict); + ecma_value_t result = ecma_internal_method_delete (target_obj_p, prop_name_p, is_strict); JERRY_BLOCK_TAIL_CALL_OPTIMIZATION (); return result; } @@ -1392,7 +1396,7 @@ ecma_proxy_object_delete_property (ecma_object_t *obj_p, /**< proxy object */ ecma_value_t args[] = { target, prop_name_value }; /* 9. */ - ecma_value_t trap_result = ecma_op_function_call (func_obj_p, handler, args, 2); + ecma_value_t trap_result = ecma_internal_method_call (func_obj_p, handler, args, 2); ecma_deref_object (func_obj_p); @@ -1418,38 +1422,38 @@ ecma_proxy_object_delete_property (ecma_object_t *obj_p, /**< proxy object */ } /* 12. */ - ecma_property_descriptor_t target_desc; - - ecma_value_t status = ecma_op_object_get_own_property_descriptor (target_obj_p, prop_name_p, &target_desc); + ecma_property_descriptor_t prop_desc = ecma_internal_method_get_own_property (target_obj_p, prop_name_p); /* 13. */ - if (ECMA_IS_VALUE_ERROR (status)) + if (ecma_property_descriptor_error (&prop_desc)) { - return status; + ecma_free_property_descriptor (&prop_desc); + return ECMA_VALUE_ERROR; } /* 14. */ - if (ecma_is_value_false (status)) + if (!ecma_property_descriptor_found (&prop_desc)) { + ecma_free_property_descriptor (&prop_desc); return ECMA_VALUE_TRUE; } ecma_value_t ret_value = ECMA_VALUE_TRUE; /* 15. */ - if (!(target_desc.flags & JERRY_PROP_IS_CONFIGURABLE)) + if (!ecma_property_descriptor_is_configurable (&prop_desc)) { ret_value = ecma_raise_type_error (ECMA_ERR_TRAP_TRUISH_PROPERTY_NON_CONFIGURABLE); } /* ES11: 13-14 */ - ecma_value_t extensible_target = ecma_builtin_object_object_is_extensible (target_obj_p); + ecma_value_t extensible_target = ecma_internal_method_is_extensible (target_obj_p); if (!ecma_is_value_true (extensible_target)) { ret_value = ecma_raise_type_error (ECMA_ERR_TRAP_TRUISH_TARGET_NOT_EXTENSIBLE); } - ecma_free_property_descriptor (&target_desc); + ecma_free_property_descriptor (&prop_desc); /* 16. */ return ret_value; @@ -1581,8 +1585,9 @@ ecma_proxy_check_invariants_for_own_prop_keys (ecma_collection_t *trap_result, * pointer to a newly allocated list of property names - otherwise */ ecma_collection_t * -ecma_proxy_object_own_property_keys (ecma_object_t *obj_p) /**< proxy object */ +ecma_proxy_object_own_property_keys (ecma_object_t *obj_p, jerry_property_filter_t filter) /**< proxy object */ { + JERRY_UNUSED (filter); JERRY_ASSERT (ECMA_OBJECT_IS_PROXY (obj_p)); ECMA_CHECK_STACK_USAGE_RETURN (NULL); @@ -1605,7 +1610,7 @@ ecma_proxy_object_own_property_keys (ecma_object_t *obj_p) /**< proxy object */ /* 6. */ if (ecma_is_value_undefined (trap)) { - ecma_collection_t *result = ecma_op_object_own_property_keys (target_obj_p, JERRY_PROPERTY_FILTER_ALL); + ecma_collection_t *result = ecma_internal_method_own_property_keys (target_obj_p, JERRY_PROPERTY_FILTER_ALL); JERRY_BLOCK_TAIL_CALL_OPTIMIZATION (); return result; } @@ -1613,7 +1618,7 @@ ecma_proxy_object_own_property_keys (ecma_object_t *obj_p) /**< proxy object */ ecma_object_t *func_obj_p = ecma_get_object_from_value (trap); /* 7. */ - ecma_value_t trap_result_array = ecma_op_function_call (func_obj_p, handler, &target, 1); + ecma_value_t trap_result_array = ecma_internal_method_call (func_obj_p, handler, &target, 1); ecma_deref_object (func_obj_p); @@ -1641,7 +1646,7 @@ ecma_proxy_object_own_property_keys (ecma_object_t *obj_p) /**< proxy object */ } /* 10. */ - ecma_value_t extensible_target = ecma_builtin_object_object_is_extensible (target_obj_p); + ecma_value_t extensible_target = ecma_internal_method_is_extensible (target_obj_p); if (ECMA_IS_VALUE_ERROR (extensible_target)) { @@ -1650,7 +1655,7 @@ ecma_proxy_object_own_property_keys (ecma_object_t *obj_p) /**< proxy object */ } /* 11. */ - ecma_collection_t *target_keys = ecma_op_object_own_property_keys (target_obj_p, JERRY_PROPERTY_FILTER_ALL); + ecma_collection_t *target_keys = ecma_internal_method_own_property_keys (target_obj_p, JERRY_PROPERTY_FILTER_ALL); if (target_keys == NULL) { @@ -1669,21 +1674,20 @@ ecma_proxy_object_own_property_keys (ecma_object_t *obj_p) /**< proxy object */ /* 16. */ for (uint32_t i = 0; i < target_keys->item_count; i++) { - ecma_property_descriptor_t target_desc; - ecma_string_t *prop_name_p = ecma_get_prop_name_from_value (target_keys->buffer_p[i]); - ecma_value_t status = ecma_op_object_get_own_property_descriptor (target_obj_p, prop_name_p, &target_desc); + ecma_property_descriptor_t prop_desc = ecma_internal_method_get_own_property (target_obj_p, prop_name_p); - if (ECMA_IS_VALUE_ERROR (status)) + if (ecma_property_descriptor_error (&prop_desc)) { ecma_collection_free (trap_result); + ecma_free_property_descriptor (&prop_desc); goto free_target_collections; } ecma_value_t prop_value = ecma_make_prop_name_value (prop_name_p); - if (ecma_is_value_true (status) && !(target_desc.flags & JERRY_PROP_IS_CONFIGURABLE)) + if (ecma_property_descriptor_found (&prop_desc) && !ecma_property_descriptor_is_configurable (&prop_desc)) { ecma_collection_push_back (target_non_configurable_keys, prop_value); } @@ -1692,10 +1696,7 @@ ecma_proxy_object_own_property_keys (ecma_object_t *obj_p) /**< proxy object */ ecma_collection_push_back (target_configurable_keys, prop_value); } - if (ecma_is_value_true (status)) - { - ecma_free_property_descriptor (&target_desc); - } + ecma_free_property_descriptor (&prop_desc); } /* 17. */ @@ -1772,7 +1773,7 @@ ecma_proxy_object_call (ecma_object_t *obj_p, /**< proxy object */ if (ecma_is_value_undefined (trap)) { ecma_object_t *target_obj_p = ecma_get_object_from_value (target); - ecma_value_t result = ecma_op_function_call (target_obj_p, this_argument, args_p, argc); + ecma_value_t result = ecma_internal_method_call (target_obj_p, this_argument, args_p, argc); JERRY_BLOCK_TAIL_CALL_OPTIMIZATION (); return result; } @@ -1782,7 +1783,7 @@ ecma_proxy_object_call (ecma_object_t *obj_p, /**< proxy object */ ecma_value_t value_array[] = { target, this_argument, args_array }; ecma_object_t *func_obj_p = ecma_get_object_from_value (trap); /* 9. */ - ecma_value_t ret_value = ecma_op_function_call (func_obj_p, handler, value_array, 3); + ecma_value_t ret_value = ecma_internal_method_call (func_obj_p, handler, value_array, 3); ecma_deref_object (func_obj_p); ecma_free_object (args_array); @@ -1831,7 +1832,7 @@ ecma_proxy_object_construct (ecma_object_t *obj_p, /**< proxy object */ { JERRY_ASSERT (ecma_object_is_constructor (target_obj_p)); - ecma_value_t result = ecma_op_function_construct (target_obj_p, new_target_p, args_p, argc); + ecma_value_t result = ecma_internal_method_construct (target_obj_p, new_target_p, args_p, argc); JERRY_BLOCK_TAIL_CALL_OPTIMIZATION (); return result; } @@ -1844,7 +1845,7 @@ ecma_proxy_object_construct (ecma_object_t *obj_p, /**< proxy object */ ecma_value_t function_call_args[] = { target, args_array, new_target_value }; /* 9. */ - ecma_value_t new_obj = ecma_op_function_call (func_obj_p, handler, function_call_args, 3); + ecma_value_t new_obj = ecma_internal_method_call (func_obj_p, handler, function_call_args, 3); ecma_free_object (args_array); ecma_deref_object (func_obj_p); diff --git a/jerry-core/ecma/operations/ecma-proxy-object.h b/jerry-core/ecma/operations/ecma-proxy-object.h index 82537bcaef..2c3219a399 100644 --- a/jerry-core/ecma/operations/ecma-proxy-object.h +++ b/jerry-core/ecma/operations/ecma-proxy-object.h @@ -34,11 +34,9 @@ ecma_object_t *ecma_proxy_create_revocable (ecma_value_t target, ecma_value_t ha ecma_value_t ecma_proxy_revoke_cb (ecma_object_t *function_obj_p, const ecma_value_t args_p[], const uint32_t args_count); -ecma_value_t ecma_proxy_object_find (ecma_object_t *obj_p, ecma_string_t *prop_name_p); - /* Interal operations */ -ecma_value_t ecma_proxy_object_get_prototype_of (ecma_object_t *obj_p); +ecma_object_t *ecma_proxy_object_get_prototype_of (ecma_object_t *obj_p); ecma_value_t ecma_proxy_object_set_prototype_of (ecma_object_t *obj_p, ecma_value_t proto); @@ -46,15 +44,13 @@ ecma_value_t ecma_proxy_object_is_extensible (ecma_object_t *obj_p); ecma_value_t ecma_proxy_object_prevent_extensions (ecma_object_t *obj_p); -ecma_value_t ecma_proxy_object_get_own_property_descriptor (ecma_object_t *obj_p, - ecma_string_t *prop_name_p, - ecma_property_descriptor_t *prop_desc_p); +ecma_property_descriptor_t ecma_proxy_object_get_own_property (ecma_object_t *object_p, ecma_string_t *prop_name_p); ecma_value_t ecma_proxy_object_define_own_property (ecma_object_t *obj_p, ecma_string_t *prop_name_p, const ecma_property_descriptor_t *prop_desc_p); -ecma_value_t ecma_proxy_object_has (ecma_object_t *obj_p, ecma_string_t *prop_name_p); +ecma_value_t ecma_proxy_object_has_property (ecma_object_t *obj_p, ecma_string_t *prop_name_p); ecma_value_t ecma_proxy_object_get (ecma_object_t *obj_p, ecma_string_t *prop_name_p, ecma_value_t receiver); @@ -66,7 +62,7 @@ ecma_value_t ecma_proxy_object_set (ecma_object_t *obj_p, ecma_value_t ecma_proxy_object_delete_property (ecma_object_t *obj_p, ecma_string_t *prop_name_p, bool is_strict); -ecma_collection_t *ecma_proxy_object_own_property_keys (ecma_object_t *obj_p); +ecma_collection_t *ecma_proxy_object_own_property_keys (ecma_object_t *obj_p, jerry_property_filter_t filter); ecma_value_t ecma_proxy_object_call (ecma_object_t *obj_p, ecma_value_t this_argument, const ecma_value_t *args_p, uint32_t argc); @@ -76,6 +72,26 @@ ecma_value_t ecma_proxy_object_construct (ecma_object_t *obj_p, const ecma_value_t *args_p, uint32_t argc); +/** + * Virtual function table for Proxy object's internal methods + */ +#define ECMA_PROXY_OBJ_VTABLE \ + [ECMA_OBJECT_TYPE_PROXY] = { ecma_proxy_object_get_prototype_of, \ + ecma_proxy_object_set_prototype_of, \ + ecma_proxy_object_is_extensible, \ + ecma_proxy_object_prevent_extensions, \ + ecma_proxy_object_get_own_property, \ + ecma_proxy_object_define_own_property, \ + ecma_proxy_object_has_property, \ + ecma_proxy_object_get, \ + ecma_proxy_object_set, \ + ecma_proxy_object_delete_property, \ + ecma_proxy_object_own_property_keys, \ + ecma_proxy_object_call, \ + ecma_proxy_object_construct, \ + NULL, \ + NULL } + #endif /* JERRY_BUILTIN_PROXY */ /** diff --git a/jerry-core/ecma/operations/ecma-reference.c b/jerry-core/ecma/operations/ecma-reference.c index d5e970b248..7b697ceb02 100644 --- a/jerry-core/ecma/operations/ecma-reference.c +++ b/jerry-core/ecma/operations/ecma-reference.c @@ -117,22 +117,19 @@ ecma_op_resolve_super_base (ecma_object_t *lex_env_p) /**< starting lexical envi { ecma_object_t *home_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u1.home_object_cp); -#if JERRY_BUILTIN_PROXY - if (ECMA_OBJECT_IS_PROXY (home_p)) - { - return ecma_proxy_object_get_prototype_of (home_p); - } -#endif /* JERRY_BUILTIN_PROXY */ - - jmem_cpointer_t proto_cp = ecma_op_ordinary_object_get_prototype_of (home_p); + ecma_object_t *proto_p = ecma_internal_method_get_prototype_of (home_p); - if (proto_cp == JMEM_CP_NULL) + if (proto_p == NULL) { return ECMA_VALUE_NULL; } - ecma_object_t *proto_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, proto_cp); - ecma_ref_object (proto_p); +#if JERRY_BUILTIN_PROXY + if (proto_p == ECMA_OBJECT_POINTER_ERROR) + { + return ECMA_VALUE_ERROR; + } +#endif /* JERRY_BUILTIN_PROXY */ return ecma_make_object_value (proto_p); } @@ -172,7 +169,8 @@ ecma_op_is_prop_unscopable (ecma_object_t *binding_obj_p, /**< binding object */ if (ecma_is_value_object (unscopables)) { ecma_object_t *unscopables_obj_p = ecma_get_object_from_value (unscopables); - ecma_value_t get_unscopables_value = ecma_op_object_get (unscopables_obj_p, prop_name_p); + ecma_value_t get_unscopables_value = ecma_internal_method_get (unscopables_obj_p, prop_name_p, unscopables); + ecma_deref_object (unscopables_obj_p); if (ECMA_IS_VALUE_ERROR (get_unscopables_value)) @@ -227,7 +225,7 @@ ecma_op_object_bound_environment_resolve_reference_value (ecma_object_t *lex_env #if JERRY_BUILTIN_PROXY if (ECMA_OBJECT_IS_PROXY (binding_obj_p)) { - found_binding = ecma_proxy_object_has (binding_obj_p, name_p); + found_binding = ecma_proxy_object_has_property (binding_obj_p, name_p); if (!ecma_is_value_true (found_binding)) { @@ -237,7 +235,7 @@ ecma_op_object_bound_environment_resolve_reference_value (ecma_object_t *lex_env else { #endif /* JERRY_BUILTIN_PROXY */ - found_binding = ecma_op_object_find (binding_obj_p, name_p); + found_binding = ecma_op_object_find (binding_obj_p, name_p, ecma_make_object_value (binding_obj_p)); if (ECMA_IS_VALUE_ERROR (found_binding) || !ecma_is_value_found (found_binding)) { @@ -381,7 +379,7 @@ ecma_op_resolve_reference_value (ecma_object_t *lex_env_p, /**< starting lexical ecma_object_t *getter_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, get_set_pair_p->getter_cp); ecma_value_t base_value = ecma_make_object_value (binding_obj_p); - return ecma_op_function_call (getter_p, base_value, NULL, 0); + return ecma_internal_method_call (getter_p, base_value, NULL, 0); } #endif /* JERRY_LCACHE */ } diff --git a/jerry-core/ecma/operations/ecma-regexp-object.c b/jerry-core/ecma/operations/ecma-regexp-object.c index 31a479cb70..f84bbb8e11 100644 --- a/jerry-core/ecma/operations/ecma-regexp-object.c +++ b/jerry-core/ecma/operations/ecma-regexp-object.c @@ -1861,10 +1861,11 @@ ecma_regexp_exec_helper (ecma_object_t *regexp_object_p, /**< RegExp object */ /* We should only get here if the regexp is global or sticky */ JERRY_ASSERT ((re_ctx.flags & (RE_FLAG_GLOBAL | RE_FLAG_STICKY)) != 0); - ret_value = ecma_op_object_put (regexp_object_p, - ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), - ecma_make_integer_value (0), - true); + ret_value = ecma_internal_method_set (regexp_object_p, + ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), + ecma_make_integer_value (0), + ecma_make_object_value (regexp_object_p), + true); if (ECMA_IS_VALUE_ERROR (ret_value)) { @@ -1906,10 +1907,11 @@ ecma_regexp_exec_helper (ecma_object_t *regexp_object_p, /**< RegExp object */ match_length = lit_utf8_string_length (match_begin_p, (lit_utf8_size_t) (match_end_p - match_begin_p)); } - ret_value = ecma_op_object_put (regexp_object_p, - ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), - ecma_make_uint32_value ((uint32_t) index + match_length), - true); + ret_value = ecma_internal_method_set (regexp_object_p, + ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), + ecma_make_uint32_value ((uint32_t) index + match_length), + ecma_make_object_value (regexp_object_p), + true); if (ECMA_IS_VALUE_ERROR (ret_value)) { @@ -1989,7 +1991,8 @@ ecma_regexp_search_helper (ecma_value_t regexp_arg, /**< regexp argument */ /* 4. */ ecma_string_t *const last_index_str_p = ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL); - const ecma_value_t prev_last_index = ecma_op_object_get (regexp_object_p, last_index_str_p); + ecma_value_t prev_last_index = ecma_internal_method_get (regexp_object_p, last_index_str_p, regexp_arg); + if (ECMA_IS_VALUE_ERROR (prev_last_index)) { goto cleanup_string; @@ -1999,7 +2002,7 @@ ecma_regexp_search_helper (ecma_value_t regexp_arg, /**< regexp argument */ if (prev_last_index != ecma_make_uint32_value (0)) { const ecma_value_t status = - ecma_op_object_put (regexp_object_p, last_index_str_p, ecma_make_uint32_value (0), true); + ecma_internal_method_set (regexp_object_p, last_index_str_p, ecma_make_uint32_value (0), regexp_arg, true); if (ECMA_IS_VALUE_ERROR (status)) { @@ -2017,7 +2020,8 @@ ecma_regexp_search_helper (ecma_value_t regexp_arg, /**< regexp argument */ } /* 7. */ - const ecma_value_t current_last_index = ecma_op_object_get (regexp_object_p, last_index_str_p); + ecma_value_t current_last_index = ecma_internal_method_get (regexp_object_p, last_index_str_p, regexp_arg); + if (ECMA_IS_VALUE_ERROR (current_last_index)) { ecma_free_value (match); @@ -2031,7 +2035,7 @@ ecma_regexp_search_helper (ecma_value_t regexp_arg, /**< regexp argument */ /* 8. */ if (!same_value) { - result = ecma_op_object_put (regexp_object_p, last_index_str_p, prev_last_index, true); + result = ecma_internal_method_set (regexp_object_p, last_index_str_p, prev_last_index, regexp_arg, true); if (ECMA_IS_VALUE_ERROR (result)) { @@ -2162,7 +2166,7 @@ ecma_regexp_split_helper (ecma_value_t this_arg, /**< this value */ /* 13-14. */ ecma_value_t arguments[] = { this_arg, ecma_make_string_value (flags_str_p) }; - ecma_value_t splitter = ecma_op_function_construct (constructor_obj_p, constructor_obj_p, arguments, 2); + ecma_value_t splitter = ecma_internal_method_construct (constructor_obj_p, constructor_obj_p, arguments, 2); ecma_deref_ecma_string (flags_str_p); ecma_deref_object (constructor_obj_p); @@ -2237,7 +2241,7 @@ ecma_regexp_split_helper (ecma_value_t this_arg, /**< this value */ { /* 24.a-b. */ ecma_value_t index_value = ecma_make_length_value (current_index); - result = ecma_op_object_put (splitter_obj_p, lastindex_str_p, index_value, true); + result = ecma_internal_method_set (splitter_obj_p, lastindex_str_p, index_value, splitter, true); ecma_free_value (index_value); @@ -2265,7 +2269,8 @@ ecma_regexp_split_helper (ecma_value_t this_arg, /**< this value */ ecma_object_t *const match_array_p = ecma_get_object_from_value (result); /* 24.f.i. */ - result = ecma_op_object_get (splitter_obj_p, lastindex_str_p); + result = ecma_internal_method_get (splitter_obj_p, lastindex_str_p, splitter); + if (ECMA_IS_VALUE_ERROR (result)) { ecma_deref_object (match_array_p); @@ -2612,10 +2617,11 @@ ecma_regexp_replace_helper_fast (ecma_replace_context_t *ctx_p, /** string_length) { - result = ecma_op_object_put ((ecma_object_t *) re_obj_p, - ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), - ecma_make_uint32_value (0), - true); + result = ecma_internal_method_set ((ecma_object_t *) re_obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), + ecma_make_uint32_value (0), + ecma_make_object_value ((ecma_object_t *) re_obj_p), + true); if (!ECMA_IS_VALUE_ERROR (result)) { @@ -2690,7 +2696,7 @@ ecma_regexp_replace_helper_fast (ecma_replace_context_t *ctx_p, /**buffer_p, arguments_p->item_count); + ecma_internal_method_call (function_p, ECMA_VALUE_UNDEFINED, arguments_p->buffer_p, arguments_p->item_count); ecma_collection_free (arguments_p); @@ -2727,10 +2733,11 @@ ecma_regexp_replace_helper_fast (ecma_replace_context_t *ctx_p, /**buffer_p, - arguments_p->item_count); + result = ecma_internal_method_call (ecma_get_object_from_value (replace_arg), + ECMA_VALUE_UNDEFINED, + arguments_p->buffer_p, + arguments_p->item_count); ecma_collection_free (arguments_p); @@ -3350,8 +3364,11 @@ ecma_regexp_match_helper (ecma_value_t this_arg, /**< this argument */ ecma_free_value (full_unicode_value); #endif /* JERRY_ESNEXT */ - ecma_value_t set_status = - ecma_op_object_put (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), ecma_make_uint32_value (0), true); + ecma_value_t set_status = ecma_internal_method_set (obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), + ecma_make_uint32_value (0), + this_arg, + true); if (ECMA_IS_VALUE_ERROR (set_status)) { @@ -3435,15 +3452,21 @@ ecma_regexp_match_helper (ecma_value_t this_arg, /**< this argument */ index = ecma_op_advance_string_index (str_p, index, full_unicode); last_index = ecma_make_length_value (index); - ecma_value_t next_set_status = - ecma_op_object_put (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), last_index, true); + ecma_value_t next_set_status = ecma_internal_method_set (obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), + last_index, + this_arg, + true); #else /* !JERRY_ESNEXT */ ecma_number_t index = ecma_get_number_from_value (last_index); ecma_free_value (last_index); last_index = ecma_make_number_value (index + 1); - ecma_value_t next_set_status = - ecma_op_object_put (obj_p, ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), last_index, true); + ecma_value_t next_set_status = ecma_internal_method_set (obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), + last_index, + this_arg, + true); #endif /* JERRY_ESNEXT */ ecma_free_value (last_index); @@ -3491,7 +3514,7 @@ ecma_op_regexp_exec (ecma_value_t this_arg, /**< this argument */ ecma_object_t *function_p = ecma_get_object_from_value (exec); ecma_value_t arguments[] = { ecma_make_string_value (str_p) }; - ecma_value_t result = ecma_op_function_call (function_p, this_arg, arguments, 1); + ecma_value_t result = ecma_internal_method_call (function_p, this_arg, arguments, 1); ecma_deref_object (function_p); diff --git a/jerry-core/ecma/operations/ecma-string-object.c b/jerry-core/ecma/operations/ecma-string-object.c index 72f7f3aa00..1fb2028fd7 100644 --- a/jerry-core/ecma/operations/ecma-string-object.c +++ b/jerry-core/ecma/operations/ecma-string-object.c @@ -24,6 +24,7 @@ #include "ecma-helpers.h" #include "ecma-objects-general.h" #include "ecma-objects.h" +#include "ecma-ordinary-object.h" #include "jcontext.h" @@ -97,16 +98,64 @@ ecma_op_create_string_object (const ecma_value_t *arguments_list_p, /**< list of return ecma_make_object_value (object_p); } /* ecma_op_create_string_object */ +/** + * ecma string object's [[GetOwnProperty]] internal method + * + * See also: + * ECMA-262 v12, 10.4.3.1 + * + * @return ecma property descriptor t + */ +ecma_property_descriptor_t +ecma_string_object_get_own_property (ecma_object_t *obj_p, /**< the object */ + ecma_string_t *property_name_p) /**< property name */ +{ + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; + + ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); + + if (ecma_string_is_length (property_name_p)) + { + ecma_value_t prim_value_p = ext_object_p->u.cls.u3.value; + ecma_string_t *prim_value_str_p = ecma_get_string_from_value (prim_value_p); + lit_utf8_size_t length = ecma_string_get_length (prim_value_str_p); + + prop_desc.flags = ECMA_PROP_DESC_VIRTUAL_FOUND; + prop_desc.value = ecma_make_uint32_value (length); + return prop_desc; + } + + 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.cls.u3.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)) + { + ecma_char_t char_at_idx = ecma_string_get_char_at_pos (prim_value_str_p, index); + ecma_string_t *char_str_p = ecma_new_ecma_string_from_code_unit (char_at_idx); + + prop_desc.flags = ECMA_PROP_DESC_VIRTUAL_FOUND | ECMA_PROP_DESC_ENUMERABLE; + prop_desc.value = ecma_make_string_value (char_str_p); + return prop_desc; + } + } + + return ecma_ordinary_object_get_own_property (obj_p, property_name_p); +} /* ecma_string_object_get_own_property */ + /** * List names of a String object's lazy instantiated properties * * @return string values collection */ void -ecma_op_string_list_lazy_property_names (ecma_object_t *obj_p, /**< a String object */ - ecma_collection_t *prop_names_p, /**< prop name collection */ - ecma_property_counter_t *prop_counter_p, /**< property counters */ - jerry_property_filter_t filter) /**< property name filter options */ +ecma_string_object_list_lazy_property_keys (ecma_object_t *obj_p, /**< a String object */ + ecma_collection_t *prop_names_p, /**< prop name collection */ + ecma_property_counter_t *prop_counter_p, /**< property counters */ + jerry_property_filter_t filter) /**< property name filter options */ { JERRY_ASSERT (ecma_get_object_base_type (obj_p) == ECMA_OBJECT_BASE_TYPE_CLASS); @@ -122,8 +171,6 @@ ecma_op_string_list_lazy_property_names (ecma_object_t *obj_p, /**< a String obj for (lit_utf8_size_t i = 0; i < length; i++) { ecma_string_t *name_p = ecma_new_ecma_string_from_uint32 (i); - - /* the properties are enumerable (ECMA-262 v5, 15.5.5.2.9) */ ecma_collection_push_back (prop_names_p, ecma_make_string_value (name_p)); } @@ -135,7 +182,7 @@ ecma_op_string_list_lazy_property_names (ecma_object_t *obj_p, /**< a String obj ecma_collection_push_back (prop_names_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH)); prop_counter_p->string_named_props++; } -} /* ecma_op_string_list_lazy_property_names */ +} /* ecma_string_object_list_lazy_property_keys */ /** * @} diff --git a/jerry-core/ecma/operations/ecma-string-object.h b/jerry-core/ecma/operations/ecma-string-object.h index 0ebb2c1264..8d92e95207 100644 --- a/jerry-core/ecma/operations/ecma-string-object.h +++ b/jerry-core/ecma/operations/ecma-string-object.h @@ -27,10 +27,31 @@ ecma_value_t ecma_op_create_string_object (const ecma_value_t *arguments_list_p, uint32_t arguments_list_len); -void ecma_op_string_list_lazy_property_names (ecma_object_t *obj_p, - ecma_collection_t *prop_names_p, - ecma_property_counter_t *prop_counter_p, - jerry_property_filter_t filter); +ecma_property_descriptor_t ecma_string_object_get_own_property (ecma_object_t *obj_p, ecma_string_t *property_name_p); +void ecma_string_object_list_lazy_property_keys (ecma_object_t *obj_p, + ecma_collection_t *prop_names_p, + ecma_property_counter_t *prop_counter_p, + jerry_property_filter_t filter); + +/** + * Virtual function table for String object's internal methods + */ +#define ECMA_STRING_OBJ_VTABLE \ + [ECMA_OBJECT_CLASS_STRING] = { NULL, \ + NULL, \ + NULL, \ + NULL, \ + ecma_string_object_get_own_property, \ + ecma_ordinary_object_define_own_property, \ + NULL, \ + ecma_ordinary_object_get, \ + ecma_ordinary_object_set, \ + ecma_ordinary_object_delete, \ + NULL, \ + NULL, \ + NULL, \ + ecma_string_object_list_lazy_property_keys, \ + ecma_ordinary_object_delete_lazy_property } /** * @} diff --git a/jerry-core/ecma/operations/ecma-typedarray-object.c b/jerry-core/ecma/operations/ecma-typedarray-object.c index c4c4f41052..c3531c91a2 100644 --- a/jerry-core/ecma/operations/ecma-typedarray-object.c +++ b/jerry-core/ecma/operations/ecma-typedarray-object.c @@ -32,6 +32,7 @@ #include "ecma-iterator-object.h" #include "ecma-objects-general.h" #include "ecma-objects.h" +#include "ecma-ordinary-object.h" #include "ecma-shared-arraybuffer-object.h" #include "jcontext.h" @@ -992,7 +993,7 @@ ecma_op_typedarray_from_helper (ecma_value_t this_val, /**< this_arg for the abo ecma_value_t current_index = ecma_make_uint32_value (index); ecma_value_t call_args[] = { current_value, current_index }; - ecma_value_t cb_value = ecma_op_function_call (func_object_p, this_val, call_args, 2); + ecma_value_t cb_value = ecma_internal_method_call (func_object_p, this_val, call_args, 2); ecma_free_value (current_value); ecma_free_value (current_index); @@ -1854,56 +1855,53 @@ ecma_is_typedarray (ecma_value_t value) /**< the target need to be checked */ } /* ecma_is_typedarray */ /** - * Checks whether the property name is a valid element index + * ecma typedarray object's [[GetOwnProperty]] internal method * - * @return true, if valid - * false, otherwise + * See also: + * ECMA-262 v12, 10.4.5.1 + * + * @return ecma property descriptor t */ -bool -ecma_typedarray_is_element_index (ecma_string_t *property_name_p) /**< property name */ +ecma_property_descriptor_t +ecma_typedarray_object_get_own_property (ecma_object_t *obj_p, /**< the object */ + ecma_string_t *property_name_p) /**< property name */ { - ecma_number_t num = ecma_string_to_number (property_name_p); + if (ecma_prop_name_is_symbol (property_name_p)) + { + return ecma_ordinary_object_get_own_property (obj_p, property_name_p); + } - if (num == 0) + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index == ECMA_STRING_NOT_ARRAY_INDEX && !ecma_op_canonical_numeric_string (property_name_p)) { - return true; + return ecma_ordinary_object_get_own_property (obj_p, property_name_p); } - ecma_string_t *num_to_str = ecma_new_ecma_string_from_number (num); - bool is_same = ecma_compare_ecma_strings (property_name_p, num_to_str); - ecma_deref_ecma_string (num_to_str); - return is_same; -} /* ecma_typedarray_is_element_index */ + ecma_typedarray_info_t info = ecma_typedarray_get_info (obj_p); + ecma_value_t value = ecma_get_typedarray_element (&info, index); -/** - * List names of a TypedArray object's integer indexed properties - */ -void -ecma_op_typedarray_list_lazy_property_names (ecma_object_t *obj_p, /**< a TypedArray object */ - ecma_collection_t *prop_names_p, /**< prop name collection */ - ecma_property_counter_t *prop_counter_p, /**< property counters */ - jerry_property_filter_t filter) /**< property name filter options */ -{ - JERRY_ASSERT (ecma_object_is_typedarray (obj_p)); + ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); - if (filter & JERRY_PROPERTY_FILTER_EXCLUDE_INTEGER_INDICES) + if (ECMA_IS_VALUE_ERROR (value)) { - return; + prop_desc.flags = ECMA_PROP_DESC_ERROR; + return prop_desc; } - uint32_t array_length = ecma_typedarray_get_length (obj_p); - - for (uint32_t i = 0; i < array_length; i++) + if (JERRY_LIKELY (!ecma_is_value_undefined (value))) { - ecma_string_t *name_p = ecma_new_ecma_string_from_uint32 (i); - ecma_collection_push_back (prop_names_p, ecma_make_string_value (name_p)); + prop_desc.flags = ECMA_PROP_DESC_VIRTUAL_FOUND | ECMA_PROP_DESC_DATA_ENUMERABLE_WRITABLE; + prop_desc.value = value; + return prop_desc; } - prop_counter_p->array_index_named_props += array_length; -} /* ecma_op_typedarray_list_lazy_property_names */ + prop_desc.flags = ECMA_PROP_DESC_VIRTUAL_NOT_FOUND_AND_STOP; + return prop_desc; +} /* ecma_typedarray_object_get_own_property */ /** - * [[DefineOwnProperty]] operation for TypedArray objects + * ecma typedarray object's [[DefineOwnProperty]] internal method * * See also: ES2015 9.4.5.3 * @@ -1912,22 +1910,23 @@ ecma_op_typedarray_list_lazy_property_names (ecma_object_t *obj_p, /**< a TypedA * raised TypeError - otherwise */ ecma_value_t -ecma_op_typedarray_define_own_property (ecma_object_t *obj_p, /**< TypedArray object */ - ecma_string_t *property_name_p, /**< property name */ - const ecma_property_descriptor_t *property_desc_p) /**< property descriptor */ +ecma_typedarray_object_define_own_property ( + ecma_object_t *obj_p, /**< TypedArray object */ + ecma_string_t *property_name_p, /**< property name */ + const ecma_property_descriptor_t *property_desc_p) /**< property descriptor */ { JERRY_ASSERT (ecma_object_is_typedarray (obj_p)); if (JERRY_UNLIKELY (ecma_prop_name_is_symbol (property_name_p))) { - return ecma_op_general_object_define_own_property (obj_p, property_name_p, property_desc_p); + return ecma_ordinary_object_define_own_property (obj_p, property_name_p, property_desc_p); } uint32_t index = ecma_string_get_array_index (property_name_p); - if (index == ECMA_STRING_NOT_ARRAY_INDEX && !ecma_typedarray_is_element_index (property_name_p)) + if (index == ECMA_STRING_NOT_ARRAY_INDEX && !ecma_op_canonical_numeric_string (property_name_p)) { - return ecma_op_general_object_define_own_property (obj_p, property_name_p, property_desc_p); + return ecma_ordinary_object_define_own_property (obj_p, property_name_p, property_desc_p); } if ((property_desc_p->flags & (JERRY_PROP_IS_GET_DEFINED | JERRY_PROP_IS_SET_DEFINED)) @@ -1945,7 +1944,7 @@ ecma_op_typedarray_define_own_property (ecma_object_t *obj_p, /**< TypedArray ob if (index >= info.length || ecma_arraybuffer_is_detached (info.array_buffer_p)) { - return ECMA_VALUE_FALSE; + return ecma_raise_property_redefinition (property_name_p, property_desc_p->flags); } if (property_desc_p->flags & JERRY_PROP_IS_VALUE_DEFINED) @@ -1959,7 +1958,94 @@ ecma_op_typedarray_define_own_property (ecma_object_t *obj_p, /**< TypedArray ob } return ECMA_VALUE_TRUE; -} /* ecma_op_typedarray_define_own_property */ +} /* ecma_typedarray_define_own_property */ + +/** + * ecma typedarray object's [[Get]] internal method + * + * See also: + * ECMA-262 v12, 10.4.5.4 + * + * @return ecma value t + */ +ecma_value_t +ecma_typedarray_object_get (ecma_object_t *obj_p, /**< the object */ + ecma_string_t *property_name_p, /**< property name */ + ecma_value_t receiver) /**< receiver */ +{ + if (JERRY_UNLIKELY (ecma_prop_name_is_symbol (property_name_p))) + { + return ecma_ordinary_object_get (obj_p, property_name_p, receiver); + } + + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index == ECMA_STRING_NOT_ARRAY_INDEX && !ecma_op_canonical_numeric_string (property_name_p)) + { + return ecma_ordinary_object_get (obj_p, property_name_p, receiver); + } + + ecma_typedarray_info_t info = ecma_typedarray_get_info (obj_p); + return ecma_get_typedarray_element (&info, index); +} /* ecma_typedarray_object_get */ + +/** + * ecma typedarray object's [[Set]] internal method + * + * See also: + * ECMA-262 v12, 10.4.5.5 + * + * @return ecma value t + */ +ecma_value_t +ecma_typedarray_object_set (ecma_object_t *obj_p, /**< the object */ + ecma_string_t *property_name_p, /**< property name */ + ecma_value_t value, /**< ecma value */ + ecma_value_t receiver, /**< receiver */ + bool is_throw) /**< flag that controls failure handling */ +{ + if (JERRY_UNLIKELY (ecma_prop_name_is_symbol (property_name_p))) + { + return ecma_ordinary_object_set (obj_p, property_name_p, value, receiver, is_throw); + } + + uint32_t index = ecma_string_get_array_index (property_name_p); + + if (index == ECMA_STRING_NOT_ARRAY_INDEX && !ecma_op_canonical_numeric_string (property_name_p)) + { + return ecma_ordinary_object_set (obj_p, property_name_p, value, receiver, is_throw); + } + + ecma_typedarray_info_t info = ecma_typedarray_get_info (obj_p); + return ecma_set_typedarray_element (&info, value, index); +} /* ecma_typedarray_object_set */ + +/** + * List names of a TypedArray object's integer indexed properties + */ +void +ecma_typedarray_object_list_lazy_property_keys (ecma_object_t *obj_p, /**< a TypedArray object */ + ecma_collection_t *prop_names_p, /**< prop name collection */ + ecma_property_counter_t *prop_counter_p, /**< property counters */ + jerry_property_filter_t filter) /**< property name filter options */ +{ + JERRY_ASSERT (ecma_object_is_typedarray (obj_p)); + + if (filter & JERRY_PROPERTY_FILTER_EXCLUDE_INTEGER_INDICES) + { + return; + } + + uint32_t array_length = ecma_typedarray_get_length (obj_p); + + for (uint32_t i = 0; i < array_length; i++) + { + ecma_string_t *name_p = ecma_new_ecma_string_from_uint32 (i); + ecma_collection_push_back (prop_names_p, ecma_make_string_value (name_p)); + } + + prop_counter_p->array_index_named_props += array_length; +} /* ecma_typedarray_object_list_lazy_property_keys */ /** * Specify the creation of a new TypedArray @@ -1979,7 +2065,7 @@ ecma_typedarray_create (ecma_object_t *constructor_p, /**< constructor function uint32_t arguments_list_len) /**< length of argument list */ { ecma_value_t ret_val = - ecma_op_function_construct (constructor_p, constructor_p, arguments_list_p, arguments_list_len); + ecma_internal_method_construct (constructor_p, constructor_p, arguments_list_p, arguments_list_len); if (ECMA_IS_VALUE_ERROR (ret_val)) { return ret_val; diff --git a/jerry-core/ecma/operations/ecma-typedarray-object.h b/jerry-core/ecma/operations/ecma-typedarray-object.h index ab004265c9..6ac9caa333 100644 --- a/jerry-core/ecma/operations/ecma-typedarray-object.h +++ b/jerry-core/ecma/operations/ecma-typedarray-object.h @@ -56,14 +56,7 @@ ecma_value_t ecma_typedarray_iterators_helper (ecma_value_t this_arg, ecma_itera bool ecma_object_is_typedarray (ecma_object_t *obj_p); bool ecma_is_typedarray (ecma_value_t target); -bool ecma_typedarray_is_element_index (ecma_string_t *property_name_p); -void ecma_op_typedarray_list_lazy_property_names (ecma_object_t *obj_p, - ecma_collection_t *prop_names_p, - ecma_property_counter_t *prop_counter_p, - jerry_property_filter_t filter); -ecma_value_t ecma_op_typedarray_define_own_property (ecma_object_t *obj_p, - ecma_string_t *property_name_p, - const ecma_property_descriptor_t *property_desc_p); +bool ecma_op_canonical_numeric_string (ecma_string_t *property_name_p); ecma_value_t ecma_op_create_typedarray_with_type_and_length (ecma_typedarray_type_t typedarray_id, uint32_t array_length); ecma_typedarray_info_t ecma_typedarray_get_info (ecma_object_t *typedarray_p); @@ -80,6 +73,41 @@ ecma_value_t ecma_typedarray_create (ecma_object_t *constructor_p, ecma_value_t *arguments_list_p, uint32_t arguments_list_len); ecma_value_t ecma_typedarray_species_create (ecma_value_t this_arg, ecma_value_t *length, uint32_t arguments_list_len); +ecma_property_descriptor_t ecma_typedarray_object_get_own_property (ecma_object_t *obj_p, + ecma_string_t *property_name_p); +ecma_value_t ecma_typedarray_object_define_own_property (ecma_object_t *obj_p, + ecma_string_t *property_name_p, + const ecma_property_descriptor_t *property_desc_p); +ecma_value_t ecma_typedarray_object_get (ecma_object_t *obj_p, ecma_string_t *property_name_p, ecma_value_t receiver); +ecma_value_t ecma_typedarray_object_set (ecma_object_t *obj_p, + ecma_string_t *property_name_p, + ecma_value_t value, + ecma_value_t receiver, + bool is_throw); +void ecma_typedarray_object_list_lazy_property_keys (ecma_object_t *obj_p, + ecma_collection_t *prop_names_p, + ecma_property_counter_t *prop_counter_p, + jerry_property_filter_t filter); + +/** + * Virtual function table for typedarray object's internal methods + */ +#define ECMA_TYPEDARRAY_OBJ_VTABLE \ + [ECMA_OBJECT_CLASS_TYPEDARRAY] = { NULL, \ + NULL, \ + NULL, \ + NULL, \ + ecma_typedarray_object_get_own_property, \ + ecma_typedarray_object_define_own_property, \ + NULL, \ + ecma_typedarray_object_get, \ + ecma_typedarray_object_set, \ + ecma_ordinary_object_delete, \ + NULL, \ + NULL, \ + NULL, \ + ecma_typedarray_object_list_lazy_property_keys, \ + ecma_ordinary_object_delete_lazy_property } /** * @} * @} diff --git a/jerry-core/include/jerryscript-types.h b/jerry-core/include/jerryscript-types.h index 4c12fb437f..83edec40e4 100644 --- a/jerry-core/include/jerryscript-types.h +++ b/jerry-core/include/jerryscript-types.h @@ -183,13 +183,13 @@ typedef enum JERRY_PROP_IS_ENUMERABLE = (1 << 1), /**< [[Enumerable]] */ JERRY_PROP_IS_WRITABLE = (1 << 2), /**< [[Writable]] */ - JERRY_PROP_IS_CONFIGURABLE_DEFINED = (1 << 3), /**< is [[Configurable]] defined? */ - JERRY_PROP_IS_ENUMERABLE_DEFINED = (1 << 4), /**< is [[Enumerable]] defined? */ - JERRY_PROP_IS_WRITABLE_DEFINED = (1 << 5), /**< is [[Writable]] defined? */ + JERRY_PROP_IS_VALUE_DEFINED = (1 << 3), /**< is [[Value]] defined? */ + JERRY_PROP_IS_GET_DEFINED = (1 << 4), /**< is [[Get]] defined? */ + JERRY_PROP_IS_SET_DEFINED = (1 << 5), /**< is [[Set]] defined? */ - JERRY_PROP_IS_VALUE_DEFINED = (1 << 6), /**< is [[Value]] defined? */ - JERRY_PROP_IS_GET_DEFINED = (1 << 7), /**< is [[Get]] defined? */ - JERRY_PROP_IS_SET_DEFINED = (1 << 8), /**< is [[Set]] defined? */ + JERRY_PROP_IS_CONFIGURABLE_DEFINED = (1 << 6), /**< is [[Configurable]] defined? */ + JERRY_PROP_IS_ENUMERABLE_DEFINED = (1 << 7), /**< is [[Enumerable]] defined? */ + JERRY_PROP_IS_WRITABLE_DEFINED = (1 << 8), /**< is [[Writable]] defined? */ JERRY_PROP_SHOULD_THROW = (1 << 9), /**< should throw on error, instead of returning with false */ } jerry_property_descriptor_flags_t; diff --git a/jerry-core/parser/js/js-parser-expr.c b/jerry-core/parser/js/js-parser-expr.c index 67b69d2c76..b2811a93e9 100644 --- a/jerry-core/parser/js/js-parser-expr.c +++ b/jerry-core/parser/js/js-parser-expr.c @@ -3525,8 +3525,8 @@ parser_process_logical_assignment_token (parser_context_t *context_p) /**< conte parser_stack_pop_uint8 (context_p); parser_process_binary_assignment_token (context_p, token); - parser_branch_t prop_reference_branch; - parser_emit_cbc_forward_branch (context_p, CBC_JUMP_FORWARD, &prop_reference_branch); + parser_branch_t prop_descerence_branch; + parser_emit_cbc_forward_branch (context_p, CBC_JUMP_FORWARD, &prop_descerence_branch); parser_set_branch_to_current_position (context_p, &condition_branch); parser_emit_cbc_ext (context_p, CBC_EXT_POP_REFERENCE); @@ -3534,7 +3534,7 @@ parser_process_logical_assignment_token (parser_context_t *context_p) /**< conte JERRY_ASSERT (context_p->stack_limit - context_p->stack_depth >= 2); PARSER_PLUS_EQUAL_U16 (context_p->stack_depth, 2); - parser_set_branch_to_current_position (context_p, &prop_reference_branch); + parser_set_branch_to_current_position (context_p, &prop_descerence_branch); } /* parser_process_logical_assignment_token */ #endif /* JERRY_ESNEXT */ diff --git a/jerry-core/parser/js/js-parser-tagged-template-literal.c b/jerry-core/parser/js/js-parser-tagged-template-literal.c index 24c4aa2ff5..23b21b135b 100644 --- a/jerry-core/parser/js/js-parser-tagged-template-literal.c +++ b/jerry-core/parser/js/js-parser-tagged-template-literal.c @@ -20,6 +20,7 @@ #include "ecma-gc.h" #include "ecma-helpers.h" #include "ecma-objects.h" +#include "ecma-ordinary-object.h" #include "js-lexer.h" @@ -139,7 +140,7 @@ static void parser_tagged_template_literal_freeze_array (ecma_object_t *obj_p) { JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_ARRAY); - ecma_op_ordinary_object_prevent_extensions (obj_p); + ecma_ordinary_object_prevent_extensions (obj_p); ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p; ext_obj_p->u.array.length_prop_and_hole_count &= (uint32_t) ~ECMA_PROPERTY_FLAG_WRITABLE; } /* parser_tagged_template_literal_freeze_array */ diff --git a/jerry-core/vm/opcodes-ecma-relational-equality.c b/jerry-core/vm/opcodes-ecma-relational-equality.c index 23040e032a..fab64a0361 100644 --- a/jerry-core/vm/opcodes-ecma-relational-equality.c +++ b/jerry-core/vm/opcodes-ecma-relational-equality.c @@ -117,7 +117,7 @@ opfunc_instanceof (ecma_value_t left_value, /**< left value */ if (JERRY_UNLIKELY (!ecma_is_value_undefined (has_instance_method))) { ecma_object_t *method_obj_p = ecma_get_object_from_value (has_instance_method); - ecma_value_t has_instance_result = ecma_op_function_call (method_obj_p, right_value, &left_value, 1); + ecma_value_t has_instance_result = ecma_internal_method_call (method_obj_p, right_value, &left_value, 1); ecma_free_value (has_instance_method); @@ -164,7 +164,7 @@ opfunc_in (ecma_value_t left_value, /**< left value */ } ecma_object_t *right_value_obj_p = ecma_get_object_from_value (right_value); - ecma_value_t result = ecma_op_object_has_property (right_value_obj_p, property_name_p); + ecma_value_t result = ecma_internal_method_has_property (right_value_obj_p, property_name_p); ecma_deref_ecma_string (property_name_p); return result; } /* opfunc_in */ diff --git a/jerry-core/vm/opcodes.c b/jerry-core/vm/opcodes.c index 9819f343b2..fdad704394 100644 --- a/jerry-core/vm/opcodes.c +++ b/jerry-core/vm/opcodes.c @@ -210,7 +210,7 @@ vm_op_delete_prop (ecma_value_t object, /**< base object */ ecma_object_t *obj_p = ecma_get_object_from_value (obj_value); JERRY_ASSERT (!ecma_is_lexical_environment (obj_p)); - ecma_value_t delete_op_ret = ecma_op_object_delete (obj_p, name_string_p, is_strict); + ecma_value_t delete_op_ret = ecma_internal_method_delete (obj_p, name_string_p, is_strict); JERRY_ASSERT (ecma_is_value_boolean (delete_op_ret) || ECMA_IS_VALUE_ERROR (delete_op_ret)); ecma_deref_object (obj_p); ecma_deref_ecma_string (name_string_p); @@ -991,13 +991,13 @@ opfunc_define_field (ecma_value_t base, ecma_value_t property, ecma_value_t valu JERRY_ASSERT (property_key_p != NULL); ecma_object_t *obj_p = ecma_get_object_from_value (base); - ecma_property_descriptor_t desc = ecma_make_empty_property_descriptor (); + ecma_property_descriptor_t desc = ecma_make_empty_define_property_descriptor (); desc.value = value; desc.flags = (JERRY_PROP_IS_WRITABLE | JERRY_PROP_IS_WRITABLE_DEFINED | JERRY_PROP_IS_ENUMERABLE | JERRY_PROP_IS_ENUMERABLE_DEFINED | JERRY_PROP_IS_CONFIGURABLE | JERRY_PROP_IS_CONFIGURABLE_DEFINED | JERRY_PROP_IS_VALUE_DEFINED | JERRY_PROP_SHOULD_THROW); - ecma_value_t result = ecma_op_object_define_own_property (obj_p, property_key_p, &desc); + ecma_value_t result = ecma_internal_method_define_own_property (obj_p, property_key_p, &desc); ecma_deref_ecma_string (property_key_p); return result; @@ -1448,7 +1448,7 @@ opfunc_private_set (ecma_value_t base, /**< this object */ { ecma_object_t *setter_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, get_set_pair_p->setter_cp); - result = ecma_op_function_call (setter_p, base, &value, 1); + result = ecma_internal_method_call (setter_p, base, &value, 1); } } @@ -1503,7 +1503,7 @@ opfunc_private_get (ecma_value_t base, /**< this object */ else { ecma_object_t *getter_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, get_set_pair_p->getter_cp); - result = ecma_op_function_call (getter_p, base, NULL, 0); + result = ecma_internal_method_call (getter_p, base, NULL, 0); } } @@ -2023,7 +2023,7 @@ opfunc_form_super_reference (ecma_value_t **vm_stack_top_p, /**< current vm stac return ECMA_VALUE_ERROR; } - ecma_value_t result = ecma_op_object_get_with_receiver (parent_p, prop_name_p, frame_ctx_p->this_binding); + ecma_value_t result = ecma_internal_method_get (parent_p, prop_name_p, frame_ctx_p->this_binding); ecma_deref_ecma_string (prop_name_p); ecma_deref_object (parent_p); @@ -2076,7 +2076,7 @@ opfunc_assign_super_reference (ecma_value_t **vm_stack_top_p, /**< vm stack top bool is_strict = (frame_ctx_p->status_flags & VM_FRAME_CTX_IS_STRICT) != 0; ecma_value_t result = - ecma_op_object_put_with_receiver (base_obj_p, prop_name_p, stack_top_p[-1], frame_ctx_p->this_binding, is_strict); + ecma_internal_method_set (base_obj_p, prop_name_p, stack_top_p[-1], frame_ctx_p->this_binding, is_strict); ecma_deref_ecma_string (prop_name_p); ecma_deref_object (base_obj_p); @@ -2134,7 +2134,7 @@ opfunc_copy_data_properties (ecma_value_t target_object, /**< target object */ } ecma_object_t *source_object_p = ecma_get_object_from_value (source_object); - ecma_collection_t *names_p = ecma_op_object_own_property_keys (source_object_p, JERRY_PROPERTY_FILTER_ALL); + ecma_collection_t *names_p = ecma_internal_method_own_property_keys (source_object_p, JERRY_PROPERTY_FILTER_ALL); #if JERRY_BUILTIN_PROXY if (names_p == NULL) @@ -2187,41 +2187,47 @@ opfunc_copy_data_properties (ecma_value_t target_object, /**< target object */ } } - ecma_property_descriptor_t descriptor; - result = ecma_op_object_get_own_property_descriptor (source_object_p, property_name_p, &descriptor); + ecma_property_descriptor_t prop_desc = ecma_internal_method_get_own_property (source_object_p, property_name_p); - if (ECMA_IS_VALUE_ERROR (result)) + if (ecma_property_descriptor_error (&prop_desc)) { + result = ECMA_VALUE_ERROR; + ecma_free_property_descriptor (&prop_desc); break; } - if (result == ECMA_VALUE_FALSE) + if (!ecma_property_descriptor_found (&prop_desc)) { + result = ECMA_VALUE_FALSE; + ecma_free_property_descriptor (&prop_desc); continue; } - if (!(descriptor.flags & JERRY_PROP_IS_ENUMERABLE)) + result = ECMA_VALUE_TRUE; + + if (!ecma_property_descriptor_is_enumerable (&prop_desc)) { - ecma_free_property_descriptor (&descriptor); + ecma_free_property_descriptor (&prop_desc); continue; } - if ((descriptor.flags & JERRY_PROP_IS_VALUE_DEFINED) && !ECMA_OBJECT_IS_PROXY (source_object_p)) + if (ecma_property_descriptor_is_data_descriptor (&prop_desc) && !ECMA_OBJECT_IS_PROXY (source_object_p)) { - result = descriptor.value; + result = ecma_copy_value (ecma_property_descriptor_value (&prop_desc)); } else { - ecma_free_property_descriptor (&descriptor); - - result = ecma_op_object_get (source_object_p, property_name_p); + result = ecma_internal_method_get (source_object_p, property_name_p, source_object); if (ECMA_IS_VALUE_ERROR (result)) { + ecma_free_property_descriptor (&prop_desc); break; } } + ecma_free_property_descriptor (&prop_desc); + opfunc_set_data_property (target_object_p, property_name_p, result); ecma_free_value (result); @@ -2279,28 +2285,23 @@ opfunc_lexical_scope_has_restricted_binding (vm_frame_ctx_t *frame_ctx_p, /**< f ecma_object_t *global_obj_p = ecma_get_object_from_value (frame_ctx_p->this_binding); -#if JERRY_BUILTIN_PROXY - if (ECMA_OBJECT_IS_PROXY (global_obj_p)) - { - ecma_property_descriptor_t prop_desc; - ecma_value_t status = ecma_proxy_object_get_own_property_descriptor (global_obj_p, name_p, &prop_desc); + ecma_property_descriptor_t prop_desc = ecma_internal_method_get_own_property (global_obj_p, name_p); - if (ecma_is_value_true (status)) - { - status = ecma_make_boolean_value ((prop_desc.flags & JERRY_PROP_IS_CONFIGURABLE) == 0); - ecma_free_property_descriptor (&prop_desc); - } + ecma_value_t ret_value; - return status; + if (ecma_property_descriptor_error (&prop_desc)) + { + ret_value = ECMA_VALUE_ERROR; + } + else + { + ret_value = ecma_make_boolean_value (ecma_property_descriptor_found (&prop_desc) + && !ecma_property_descriptor_is_configurable (&prop_desc)); } -#endif /* JERRY_BUILTIN_PROXY */ - - ecma_property_t property = ecma_op_object_get_own_property (global_obj_p, name_p, NULL, ECMA_PROPERTY_GET_NO_OPTIONS); - JERRY_ASSERT (property == ECMA_PROPERTY_TYPE_NOT_FOUND || ECMA_PROPERTY_IS_FOUND (property)); + ecma_free_property_descriptor (&prop_desc); - return ecma_make_boolean_value (property != ECMA_PROPERTY_TYPE_NOT_FOUND - && !ecma_is_property_configurable (property)); + return ret_value; } /* opfunc_lexical_scope_has_restricted_binding */ #endif /* JERRY_ESNEXT */ diff --git a/jerry-core/vm/vm-stack.c b/jerry-core/vm/vm-stack.c index 38a9e72da5..3359163fad 100644 --- a/jerry-core/vm/vm-stack.c +++ b/jerry-core/vm/vm-stack.c @@ -375,7 +375,7 @@ vm_stack_find_finally (vm_frame_ctx_t *frame_ctx_p, /**< frame context */ if (!ECMA_IS_VALUE_ERROR (result) && !ecma_is_value_undefined (result)) { ecma_object_t *return_obj_p = ecma_get_object_from_value (result); - result = ecma_op_function_validated_call (result, iterator, NULL, 0); + result = ecma_internal_method_validated_call (result, iterator, NULL, 0); ecma_deref_object (return_obj_p); if (context_type == VM_CONTEXT_FOR_AWAIT_OF && !ECMA_IS_VALUE_ERROR (result)) diff --git a/jerry-core/vm/vm.c b/jerry-core/vm/vm.c index 95b5840dd2..ca53b8d0d2 100644 --- a/jerry-core/vm/vm.c +++ b/jerry-core/vm/vm.c @@ -33,6 +33,7 @@ #include "ecma-lex-env.h" #include "ecma-objects-general.h" #include "ecma-objects.h" +#include "ecma-ordinary-object.h" #include "ecma-promise-object.h" #include "ecma-regexp-object.h" @@ -115,7 +116,7 @@ vm_op_get_value (ecma_value_t object, /**< base object */ #endif /* JERRY_LCACHE */ /* There is no need to free the name. */ - return ecma_op_object_get (object_p, property_name_p); + return ecma_internal_method_get (object_p, property_name_p, object); } } @@ -195,9 +196,9 @@ vm_op_set_value (ecma_value_t base, /**< base object */ JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (object)); object_p = ecma_get_object_from_value (object); - ecma_op_ordinary_object_prevent_extensions (object_p); + ecma_ordinary_object_prevent_extensions (object_p); - result = ecma_op_object_put_with_receiver (object_p, property_p, value, base, is_strict); + result = ecma_internal_method_set (object_p, property_p, value, base, is_strict); ecma_free_value (base); } @@ -223,7 +224,7 @@ vm_op_set_value (ecma_value_t base, /**< base object */ if (!ecma_is_lexical_environment (object_p)) { - result = ecma_op_object_put_with_receiver (object_p, property_p, value, base, is_strict); + result = ecma_internal_method_set (object_p, property_p, value, base, is_strict); } else { @@ -575,8 +576,10 @@ vm_super_call (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ else { ecma_object_t *func_obj_p = ecma_get_object_from_value (func_value); - completion_value = - ecma_op_function_construct (func_obj_p, JERRY_CONTEXT (current_new_target_p), arguments_p, arguments_list_len); + completion_value = ecma_internal_method_construct (func_obj_p, + JERRY_CONTEXT (current_new_target_p), + arguments_p, + arguments_list_len); if (!ECMA_IS_VALUE_ERROR (completion_value) && ecma_op_this_binding_is_initialized (environment_record_p)) { @@ -670,27 +673,18 @@ vm_spread_operation (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ { ecma_object_t *constructor_obj_p = ecma_get_object_from_value (func_value); - completion_value = ecma_op_function_construct (constructor_obj_p, - constructor_obj_p, - collection_p->buffer_p, - collection_p->item_count); + completion_value = ecma_internal_method_construct (constructor_obj_p, + constructor_obj_p, + collection_p->buffer_p, + collection_p->item_count); } } else { ecma_value_t this_value = is_call_prop ? frame_ctx_p->stack_top_p[-2] : ECMA_VALUE_UNDEFINED; - if (!ecma_is_value_object (func_value) || !ecma_op_object_is_callable (ecma_get_object_from_value (func_value))) - { - completion_value = ecma_raise_type_error (ECMA_ERR_EXPECTED_A_FUNCTION); - } - else - { - ecma_object_t *func_obj_p = ecma_get_object_from_value (func_value); - - completion_value = - ecma_op_function_call (func_obj_p, this_value, collection_p->buffer_p, collection_p->item_count); - } + completion_value = + ecma_internal_method_validated_call (func_value, this_value, collection_p->buffer_p, collection_p->item_count); if (is_call_prop) { @@ -761,7 +755,7 @@ opfunc_call (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ ecma_value_t func_value = stack_top_p[-1]; ecma_value_t completion_value = - ecma_op_function_validated_call (func_value, this_value, stack_top_p, arguments_list_len); + ecma_internal_method_validated_call (func_value, this_value, stack_top_p, arguments_list_len); JERRY_CONTEXT (status_flags) &= (uint32_t) ~ECMA_STATUS_DIRECT_EVAL; @@ -843,7 +837,7 @@ opfunc_construct (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ ecma_object_t *constructor_obj_p = ecma_get_object_from_value (constructor_value); completion_value = - ecma_op_function_construct (constructor_obj_p, constructor_obj_p, stack_top_p, arguments_list_len); + ecma_internal_method_construct (constructor_obj_p, constructor_obj_p, stack_top_p, arguments_list_len); } /* Free registers. */ @@ -1808,7 +1802,8 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ } case VM_OC_CLASS_CALL_STATIC_BLOCK: { - result = ecma_op_function_call (ecma_get_object_from_value (left_value), frame_ctx_p->this_binding, NULL, 0); + result = + ecma_internal_method_call (ecma_get_object_from_value (left_value), frame_ctx_p->this_binding, NULL, 0); if (ECMA_IS_VALUE_ERROR (result)) { @@ -4160,7 +4155,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ { ecma_string_t *prop_name_p = ecma_get_prop_name_from_value (buffer_p[index]); - result = ecma_op_object_has_property (object_p, prop_name_p); + result = ecma_internal_method_has_property (object_p, prop_name_p); if (ECMA_IS_VALUE_ERROR (result)) { diff --git a/tests/test262-esnext-excludelist.xml b/tests/test262-esnext-excludelist.xml index 742cb67d7c..e217b9f89f 100644 --- a/tests/test262-esnext-excludelist.xml +++ b/tests/test262-esnext-excludelist.xml @@ -1,7 +1,6 @@ - @@ -145,13 +144,7 @@ - - - - - -