diff --git a/src/libecmabuiltins/ecma-builtin-global-object.c b/src/libecmabuiltins/ecma-builtin-global-object.c index 831bb9f25..d2a114dcc 100644 --- a/src/libecmabuiltins/ecma-builtin-global-object.c +++ b/src/libecmabuiltins/ecma-builtin-global-object.c @@ -13,11 +13,14 @@ * limitations under the License. */ -#include "globals.h" +#include "ecma-alloc.h" #include "ecma-builtins.h" +#include "ecma-conversion.h" #include "ecma-gc.h" #include "ecma-globals.h" #include "ecma-helpers.h" +#include "ecma-try-catch-macro.h" +#include "globals.h" #define ECMA_BUILTINS_INTERNAL #include "ecma-builtins-internal.h" @@ -32,6 +35,53 @@ * @{ */ +/** + * List of the Global object's built-in property names + * + * Warning: + * values in the array should be sorted in ascending order + * that is checked in the ecma_builtin_init_global_object. + */ +static const ecma_magic_string_id_t ecma_builtin_global_property_names[] = +{ + ECMA_MAGIC_STRING_EVAL, + ECMA_MAGIC_STRING_UNDEFINED, + ECMA_MAGIC_STRING_NAN, + ECMA_MAGIC_STRING_INFINITY_UL, + ECMA_MAGIC_STRING_OBJECT_UL, + ECMA_MAGIC_STRING_FUNCTION_UL, + ECMA_MAGIC_STRING_ARRAY_UL, + ECMA_MAGIC_STRING_STRING_UL, + ECMA_MAGIC_STRING_BOOLEAN_UL, + ECMA_MAGIC_STRING_NUMBER_UL, + ECMA_MAGIC_STRING_DATE_UL, + ECMA_MAGIC_STRING_REG_EXP_UL, + ECMA_MAGIC_STRING_ERROR_UL, + ECMA_MAGIC_STRING_EVAL_ERROR_UL, + ECMA_MAGIC_STRING_RANGE_ERROR_UL, + ECMA_MAGIC_STRING_REFERENCE_ERROR_UL, + ECMA_MAGIC_STRING_SYNTAX_ERROR_UL, + ECMA_MAGIC_STRING_TYPE_ERROR_UL, + ECMA_MAGIC_STRING_URI_ERROR_UL, + ECMA_MAGIC_STRING_MATH_UL, + ECMA_MAGIC_STRING_JSON_U, + ECMA_MAGIC_STRING_PARSE_INT, + ECMA_MAGIC_STRING_PARSE_FLOAT, + ECMA_MAGIC_STRING_IS_NAN, + ECMA_MAGIC_STRING_IS_FINITE, + ECMA_MAGIC_STRING_DECODE_URI, + ECMA_MAGIC_STRING_DECODE_URI_COMPONENT, + ECMA_MAGIC_STRING_ENCODE_URI, + ECMA_MAGIC_STRING_ENCODE_URI_COMPONENT +}; + +/** + * Number of the Global object's built-in properties + */ +static const ecma_length_t ecma_builtin_global_property_number = (sizeof (ecma_builtin_global_property_names) / + sizeof (ecma_magic_string_id_t)); +JERRY_STATIC_ASSERT (sizeof (ecma_builtin_global_property_names) > sizeof (void*)); + /** * Global object */ @@ -78,16 +128,23 @@ ecma_builtin_init_global_object (void) ecma_object_t *glob_obj_p = ecma_create_object (NULL, true, ECMA_OBJECT_TYPE_GENERAL); - ecma_string_t* undefined_identifier_p = ecma_get_magic_string (ECMA_MAGIC_STRING_UNDEFINED); - ecma_property_t *undefined_prop_p = ecma_create_named_data_property (glob_obj_p, - undefined_identifier_p, - ECMA_PROPERTY_NOT_WRITABLE, - ECMA_PROPERTY_NOT_ENUMERABLE, - ECMA_PROPERTY_NOT_CONFIGURABLE); - ecma_deref_ecma_string (undefined_identifier_p); - JERRY_ASSERT(ecma_is_value_undefined (undefined_prop_p->u.named_data_property.value)); + ecma_property_t *class_prop_p = ecma_create_internal_property (glob_obj_p, + ECMA_INTERNAL_PROPERTY_CLASS); + class_prop_p->u.internal_property.value = ECMA_OBJECT_CLASS_OBJECT; - TODO(/* Define NaN, Infinity, eval, parseInt, parseFloat, isNaN, isFinite properties */); + ecma_property_t *built_in_id_prop_p = ecma_create_internal_property (glob_obj_p, + ECMA_INTERNAL_PROPERTY_BUILT_IN_ID); + built_in_id_prop_p->u.internal_property.value = ECMA_BUILTIN_ID_GLOBAL; + + ecma_property_t *mask_0_31_prop_p; + mask_0_31_prop_p = ecma_create_internal_property (glob_obj_p, + ECMA_INTERNAL_PROPERTY_NON_INSTANTIATED_BUILT_IN_MASK_0_31); + + JERRY_STATIC_ASSERT (ecma_builtin_global_property_number < sizeof (uint32_t) * JERRY_BITSINBYTE); + uint32_t builtin_mask = ((uint32_t)1u << ecma_builtin_global_property_number) - 1; + mask_0_31_prop_p->u.internal_property.value = builtin_mask; + + ecma_set_object_is_builtin (glob_obj_p, true); ecma_global_object_p = glob_obj_p; } /* ecma_builtin_init_global_object */ @@ -163,9 +220,22 @@ ecma_builtin_global_object_parse_float (ecma_value_t string) /**< routine's firs * Returned value must be freed with ecma_free_completion_value. */ static ecma_completion_value_t -ecma_builtin_global_object_is_nan (ecma_value_t number) /**< routine's first argument */ +ecma_builtin_global_object_is_nan (ecma_value_t arg) /**< routine's first argument */ { - JERRY_UNIMPLEMENTED_REF_UNUSED_VARS (number); + ecma_completion_value_t ret_value; + + ECMA_TRY_CATCH (num_value, ecma_op_to_number (arg), ret_value); + + ecma_number_t *num_p = ECMA_GET_POINTER (num_value.u.value.value); + + bool is_nan = ecma_number_is_nan (*num_p); + + ret_value = ecma_make_return_completion_value (ecma_make_simple_value (is_nan ? ECMA_SIMPLE_VALUE_TRUE + : ECMA_SIMPLE_VALUE_FALSE)); + + ECMA_FINALIZE (num_value); + + return ret_value; } /* ecma_builtin_global_object_is_nan */ /** @@ -178,9 +248,23 @@ ecma_builtin_global_object_is_nan (ecma_value_t number) /**< routine's first arg * Returned value must be freed with ecma_free_completion_value. */ static ecma_completion_value_t -ecma_builtin_global_object_is_finite (ecma_value_t number) /**< routine's first argument */ +ecma_builtin_global_object_is_finite (ecma_value_t arg) /**< routine's first argument */ { - JERRY_UNIMPLEMENTED_REF_UNUSED_VARS (number); + ecma_completion_value_t ret_value; + + ECMA_TRY_CATCH (num_value, ecma_op_to_number (arg), ret_value); + + ecma_number_t *num_p = ECMA_GET_POINTER (num_value.u.value.value); + + bool is_finite = !(ecma_number_is_nan (*num_p) + || ecma_number_is_infinity (*num_p)); + + ret_value = ecma_make_return_completion_value (ecma_make_simple_value (is_finite ? ECMA_SIMPLE_VALUE_TRUE + : ECMA_SIMPLE_VALUE_FALSE)); + + ECMA_FINALIZE (num_value); + + return ret_value; } /* ecma_builtin_global_object_is_finite */ /** @@ -249,24 +333,24 @@ ecma_builtin_global_object_encode_uri_component (ecma_value_t uri_component) /** * @return number of parameters */ ecma_length_t -ecma_builtin_global_get_routine_parameters_number (ecma_builtin_global_detail_id_t builtin_routine_id) /**< routine's - id */ +ecma_builtin_global_get_routine_parameters_number (ecma_magic_string_id_t builtin_routine_id) /**< built-in routine's + name */ { switch (builtin_routine_id) { - case ECMA_BUILTIN_GLOBAL_DETAIL_ID_EVAL: - case ECMA_BUILTIN_GLOBAL_DETAIL_ID_PARSE_FLOAT: - case ECMA_BUILTIN_GLOBAL_DETAIL_ID_IS_NAN: - case ECMA_BUILTIN_GLOBAL_DETAIL_ID_IS_FINITE: - case ECMA_BUILTIN_GLOBAL_DETAIL_ID_DECODE_URI: - case ECMA_BUILTIN_GLOBAL_DETAIL_ID_DECODE_URI_COMPONENT: - case ECMA_BUILTIN_GLOBAL_DETAIL_ID_ENCODE_URI: - case ECMA_BUILTIN_GLOBAL_DETAIL_ID_ENCODE_URI_COMPONENT: + case ECMA_MAGIC_STRING_EVAL: + case ECMA_MAGIC_STRING_PARSE_FLOAT: + case ECMA_MAGIC_STRING_IS_NAN: + case ECMA_MAGIC_STRING_IS_FINITE: + case ECMA_MAGIC_STRING_DECODE_URI: + case ECMA_MAGIC_STRING_DECODE_URI_COMPONENT: + case ECMA_MAGIC_STRING_ENCODE_URI: + case ECMA_MAGIC_STRING_ENCODE_URI_COMPONENT: { return 1; } - case ECMA_BUILTIN_GLOBAL_DETAIL_ID_PARSE_INT: + case ECMA_MAGIC_STRING_PARSE_INT: { return 2; } @@ -285,11 +369,8 @@ ecma_builtin_global_get_routine_parameters_number (ecma_builtin_global_detail_id * Returned value must be freed with ecma_free_completion_value. */ ecma_completion_value_t -ecma_builtin_global_dispatch_routine (ecma_builtin_global_detail_id_t builtin_routine_id, /**< identifier of - the Global object's - initial property that - corresponds to - routine to be called */ +ecma_builtin_global_dispatch_routine (ecma_magic_string_id_t builtin_routine_id, /**< Global object's + built-in routine's name */ ecma_value_t arguments_list [], /**< list of arguments passed to routine */ ecma_length_t arguments_number) /**< length of arguments' list */ { @@ -297,14 +378,14 @@ ecma_builtin_global_dispatch_routine (ecma_builtin_global_detail_id_t builtin_ro switch (builtin_routine_id) { - case ECMA_BUILTIN_GLOBAL_DETAIL_ID_EVAL: + case ECMA_MAGIC_STRING_EVAL: { ecma_value_t arg = (arguments_number >= 1 ? arguments_list[0] : value_undefined); return ecma_builtin_global_object_eval (arg); } - case ECMA_BUILTIN_GLOBAL_DETAIL_ID_PARSE_INT: + case ECMA_MAGIC_STRING_PARSE_INT: { ecma_value_t arg1 = (arguments_number >= 1 ? arguments_list[0] : value_undefined); ecma_value_t arg2 = (arguments_number >= 2 ? arguments_list[1] : value_undefined); @@ -312,49 +393,49 @@ ecma_builtin_global_dispatch_routine (ecma_builtin_global_detail_id_t builtin_ro return ecma_builtin_global_object_parse_int (arg1, arg2); } - case ECMA_BUILTIN_GLOBAL_DETAIL_ID_PARSE_FLOAT: + case ECMA_MAGIC_STRING_PARSE_FLOAT: { ecma_value_t arg = (arguments_number >= 1 ? arguments_list[0] : value_undefined); return ecma_builtin_global_object_parse_float (arg); } - case ECMA_BUILTIN_GLOBAL_DETAIL_ID_IS_NAN: + case ECMA_MAGIC_STRING_IS_NAN: { ecma_value_t arg = (arguments_number >= 1 ? arguments_list[0] : value_undefined); return ecma_builtin_global_object_is_nan (arg); } - case ECMA_BUILTIN_GLOBAL_DETAIL_ID_IS_FINITE: + case ECMA_MAGIC_STRING_IS_FINITE: { ecma_value_t arg = (arguments_number >= 1 ? arguments_list[0] : value_undefined); return ecma_builtin_global_object_is_finite (arg); } - case ECMA_BUILTIN_GLOBAL_DETAIL_ID_DECODE_URI: + case ECMA_MAGIC_STRING_DECODE_URI: { ecma_value_t arg = (arguments_number >= 1 ? arguments_list[0] : value_undefined); return ecma_builtin_global_object_decode_uri (arg); } - case ECMA_BUILTIN_GLOBAL_DETAIL_ID_DECODE_URI_COMPONENT: + case ECMA_MAGIC_STRING_DECODE_URI_COMPONENT: { ecma_value_t arg = (arguments_number >= 1 ? arguments_list[0] : value_undefined); return ecma_builtin_global_object_decode_uri_component (arg); } - case ECMA_BUILTIN_GLOBAL_DETAIL_ID_ENCODE_URI: + case ECMA_MAGIC_STRING_ENCODE_URI: { ecma_value_t arg = (arguments_number >= 1 ? arguments_list[0] : value_undefined); return ecma_builtin_global_object_encode_uri (arg); } - case ECMA_BUILTIN_GLOBAL_DETAIL_ID_ENCODE_URI_COMPONENT: + case ECMA_MAGIC_STRING_ENCODE_URI_COMPONENT: { ecma_value_t arg = (arguments_number >= 1 ? arguments_list[0] : value_undefined); @@ -368,6 +449,161 @@ ecma_builtin_global_dispatch_routine (ecma_builtin_global_detail_id_t builtin_ro } } /* ecma_builtin_global_dispatch_routine */ +/** + * If the property's name is one of built-in properties of the Global object + * that is not instantiated yet, instantiate the property and + * return pointer to the instantiated property. + * + * @return pointer property, if one was instantiated, + * NULL - otherwise. + */ +ecma_property_t* +ecma_builtin_global_try_to_instantiate_property (ecma_object_t *obj_p, /**< object */ + ecma_string_t *prop_name_p) /**< property's name */ +{ + JERRY_ASSERT (ecma_builtin_is_global_object (obj_p)); + JERRY_ASSERT (ecma_find_named_property (obj_p, prop_name_p) == NULL); + + ecma_magic_string_id_t id; + + if (!ecma_is_string_magic (prop_name_p, &id)) + { + return NULL; + } + + int32_t index = ecma_builtin_bin_search_for_magic_string_id_in_array (ecma_builtin_global_property_names, + ecma_builtin_global_property_number, + id); + + if (index == -1) + { + return NULL; + } + + JERRY_ASSERT (index >= 0 && (uint32_t) index < sizeof (uint32_t) * JERRY_BITSINBYTE); + + uint32_t bit = (uint32_t) 1u << index; + + ecma_property_t *mask_0_31_prop_p; + mask_0_31_prop_p = ecma_get_internal_property (obj_p, + ECMA_INTERNAL_PROPERTY_NON_INSTANTIATED_BUILT_IN_MASK_0_31); + uint32_t bit_mask = mask_0_31_prop_p->u.internal_property.value; + + if (!(bit_mask & bit)) + { + return NULL; + } + + bit_mask &= ~bit; + + mask_0_31_prop_p->u.internal_property.value = bit_mask; + + ecma_value_t value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); + ecma_property_writable_value_t writable = ECMA_PROPERTY_WRITABLE; + ecma_property_enumerable_value_t enumerable = ECMA_PROPERTY_NOT_ENUMERABLE; + ecma_property_configurable_value_t configurable = ECMA_PROPERTY_CONFIGURABLE; + + switch (id) + { + case ECMA_MAGIC_STRING_EVAL: + case ECMA_MAGIC_STRING_PARSE_INT: + case ECMA_MAGIC_STRING_PARSE_FLOAT: + case ECMA_MAGIC_STRING_IS_NAN: + case ECMA_MAGIC_STRING_IS_FINITE: + case ECMA_MAGIC_STRING_DECODE_URI: + case ECMA_MAGIC_STRING_DECODE_URI_COMPONENT: + case ECMA_MAGIC_STRING_ENCODE_URI: + case ECMA_MAGIC_STRING_ENCODE_URI_COMPONENT: + { + ecma_object_t *func_obj_p = ecma_builtin_make_function_object_for_routine (ECMA_BUILTIN_ID_GLOBAL, + id); + + value = ecma_make_object_value (func_obj_p); + + writable = ECMA_PROPERTY_NOT_WRITABLE; + enumerable = ECMA_PROPERTY_NOT_ENUMERABLE; + configurable = ECMA_PROPERTY_NOT_CONFIGURABLE; + + break; + } + case ECMA_MAGIC_STRING_UNDEFINED: + { + value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); + + writable = ECMA_PROPERTY_NOT_WRITABLE; + enumerable = ECMA_PROPERTY_NOT_ENUMERABLE; + configurable = ECMA_PROPERTY_NOT_CONFIGURABLE; + + break; + } + case ECMA_MAGIC_STRING_NAN: + { + ecma_number_t *num_p = ecma_alloc_number (); + *num_p = ecma_number_make_nan (); + + value = ecma_make_number_value (num_p); + + writable = ECMA_PROPERTY_NOT_WRITABLE; + enumerable = ECMA_PROPERTY_NOT_ENUMERABLE; + configurable = ECMA_PROPERTY_NOT_CONFIGURABLE; + + break; + } + case ECMA_MAGIC_STRING_INFINITY_UL: + { + ecma_number_t *num_p = ecma_alloc_number (); + *num_p = ecma_number_make_infinity (false); + + value = ecma_make_number_value (num_p); + + writable = ECMA_PROPERTY_NOT_WRITABLE; + enumerable = ECMA_PROPERTY_NOT_ENUMERABLE; + configurable = ECMA_PROPERTY_NOT_CONFIGURABLE; + + break; + } + case ECMA_MAGIC_STRING_OBJECT_UL: + case ECMA_MAGIC_STRING_FUNCTION_UL: + case ECMA_MAGIC_STRING_ARRAY_UL: + case ECMA_MAGIC_STRING_STRING_UL: + case ECMA_MAGIC_STRING_BOOLEAN_UL: + case ECMA_MAGIC_STRING_NUMBER_UL: + case ECMA_MAGIC_STRING_DATE_UL: + case ECMA_MAGIC_STRING_REG_EXP_UL: + case ECMA_MAGIC_STRING_ERROR_UL: + case ECMA_MAGIC_STRING_EVAL_ERROR_UL: + case ECMA_MAGIC_STRING_RANGE_ERROR_UL: + case ECMA_MAGIC_STRING_REFERENCE_ERROR_UL: + case ECMA_MAGIC_STRING_SYNTAX_ERROR_UL: + case ECMA_MAGIC_STRING_TYPE_ERROR_UL: + case ECMA_MAGIC_STRING_URI_ERROR_UL: + case ECMA_MAGIC_STRING_MATH_UL: + case ECMA_MAGIC_STRING_JSON_U: + { + JERRY_UNIMPLEMENTED (); + } + + default: + { + JERRY_UNREACHABLE (); + } + } + + ecma_property_t *prop_p = ecma_create_named_data_property (obj_p, + prop_name_p, + writable, + enumerable, + configurable); + + prop_p->u.named_data_property.value = ecma_copy_value (value, false); + ecma_gc_update_may_ref_younger_object_flag_by_value (obj_p, + prop_p->u.named_data_property.value); + + ecma_free_value (value, true); + + return prop_p; +} /* ecma_builtin_global_try_to_instantiate_property */ + /** * @} * @} diff --git a/src/libecmabuiltins/ecma-builtins-internal.h b/src/libecmabuiltins/ecma-builtins-internal.h index e8a5aa646..7a21fc684 100644 --- a/src/libecmabuiltins/ecma-builtins-internal.h +++ b/src/libecmabuiltins/ecma-builtins-internal.h @@ -52,79 +52,10 @@ typedef enum ECMA_BUILTIN_ID_TYPE_ERROR, /**< the SyntaxError object (15.11.6.5) */ ECMA_BUILTIN_ID_SYNTAX_URI_ERROR, /**< the URIError object (15.11.6.6) */ ECMA_BUILTIN_ID_MATH, /**< the Math object (15.8) */ - ECMA_BUILTIN_ID_JSON /**< the JSON object (15.12) */ + ECMA_BUILTIN_ID_JSON, /**< the JSON object (15.12) */ + ECMA_BUILTIN_ID__COUNT /**< number of built-in objects */ } ecma_builtin_id_t; -/** - * Identifier of Global object's detail - */ -typedef enum -{ - /* Non-object value properties */ - ECMA_BUILTIN_GLOBAL_DETAIL_ID_NAN, - ECMA_BUILTIN_GLOBAL_DETAIL_ID_INFINITY, - ECMA_BUILTIN_GLOBAL_DETAIL_ID_UNDEFINED, - - /* Object value properties */ - ECMA_BUILTIN_GLOBAL_DETAIL_ID_OBJECT, - ECMA_BUILTIN_GLOBAL_DETAIL_ID_FUNCTION, - ECMA_BUILTIN_GLOBAL_DETAIL_ID_ARRAY, - ECMA_BUILTIN_GLOBAL_DETAIL_ID_STRING, - ECMA_BUILTIN_GLOBAL_DETAIL_ID_BOOLEAN, - ECMA_BUILTIN_GLOBAL_DETAIL_ID_NUMBER, - ECMA_BUILTIN_GLOBAL_DETAIL_ID_DATE, - ECMA_BUILTIN_GLOBAL_DETAIL_ID_REGEXP, - ECMA_BUILTIN_GLOBAL_DETAIL_ID_ERROR, - ECMA_BUILTIN_GLOBAL_DETAIL_ID_RANGE_ERROR, - ECMA_BUILTIN_GLOBAL_DETAIL_ID_REFERENCE_ERROR, - ECMA_BUILTIN_GLOBAL_DETAIL_ID_SYNTAX_ERROR, - ECMA_BUILTIN_GLOBAL_DETAIL_ID_SYNTAX_URI_ERROR, - ECMA_BUILTIN_GLOBAL_DETAIL_ID_MATH, - ECMA_BUILTIN_GLOBAL_DETAIL_ID_JSON, - - /* Routine properties */ - ECMA_BUILTIN_GLOBAL_DETAIL_ID_EVAL, - ECMA_BUILTIN_GLOBAL_DETAIL_ID_PARSE_INT, - ECMA_BUILTIN_GLOBAL_DETAIL_ID_PARSE_FLOAT, - ECMA_BUILTIN_GLOBAL_DETAIL_ID_IS_NAN, - ECMA_BUILTIN_GLOBAL_DETAIL_ID_IS_FINITE, - ECMA_BUILTIN_GLOBAL_DETAIL_ID_DECODE_URI, - ECMA_BUILTIN_GLOBAL_DETAIL_ID_DECODE_URI_COMPONENT, - ECMA_BUILTIN_GLOBAL_DETAIL_ID_ENCODE_URI, - ECMA_BUILTIN_GLOBAL_DETAIL_ID_ENCODE_URI_COMPONENT, - - /* Details number */ - ECMA_BUILTIN_GLOBAL_DETAIL_ID__COUNT -} ecma_builtin_global_detail_id_t; - -/** - * Identifier of Object object's detail - */ -typedef enum -{ - /* Value subbuilt-ins */ - ECMA_BUILTIN_OBJECT_DETAIL_ID_PROTOTYPE, - - /* Routine subbuilt-ins */ - ECMA_BUILTIN_OBJECT_DETAIL_ID_CALL, /**< [[Call]] of the Object built-in */ - ECMA_BUILTIN_OBJECT_DETAIL_ID_CONSTRUCT, /**< [[Construct]] of the Object built-in */ - ECMA_BUILTIN_OBJECT_DETAIL_ID_GET_PROTOTYPE_OF, - ECMA_BUILTIN_OBJECT_DETAIL_ID_GET_OWN_PROPERTY_DESCRIPTOR, - ECMA_BUILTIN_OBJECT_DETAIL_ID_GET_OWN_PROPERTY_NAMES, - ECMA_BUILTIN_OBJECT_DETAIL_ID_CREATE, - ECMA_BUILTIN_OBJECT_DETAIL_ID_DEFINE_PROPERTY, - ECMA_BUILTIN_OBJECT_DETAIL_ID_DEFINE_PROPERTIES, - ECMA_BUILTIN_OBJECT_DETAIL_ID_SEAL, - ECMA_BUILTIN_OBJECT_DETAIL_ID_FREEZE, - ECMA_BUILTIN_OBJECT_DETAIL_ID_IS_SEALED, - ECMA_BUILTIN_OBJECT_DETAIL_ID_IS_FROZEN, - ECMA_BUILTIN_OBJECT_DETAIL_ID_IS_EXTENSIBLE, - ECMA_BUILTIN_OBJECT_DETAIL_ID_KEYS, - - /* Details number */ - ECMA_BUILTIN_OBJECT_DETAIL_ID__COUNT -} ecma_builtin_object_detail_id_t; - /** * Position of built-in object's id field in [[Built-in routine ID]] internal property */ @@ -145,43 +76,57 @@ typedef enum /** * Width of built-in routine's id field in [[Built-in routine ID]] internal property */ -#define ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_ROUTINE_ID_WIDTH (16)/* ecma-builtins.c */ +#define ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_ROUTINE_ID_WIDTH (16) +/* ecma-builtins.c */ extern ecma_object_t* ecma_builtin_make_function_object_for_routine (ecma_builtin_id_t builtin_id, - uint32_t routine_id); -extern ecma_length_t -ecma_builtin_get_routine_parameters_number (ecma_builtin_id_t builtin_id, - uint32_t routine_id); -extern ecma_completion_value_t -ecma_builtin_dispatch_routine (ecma_builtin_id_t builtin_object_id, - uint32_t builtin_routine_id, - ecma_value_t arguments_list[], - ecma_length_t arguments_number); + ecma_magic_string_id_t routine_id); /* ecma-builtin-global-object.c */ extern void ecma_builtin_init_global_object (void); extern void ecma_builtin_finalize_global_object (void); extern ecma_length_t -ecma_builtin_global_get_routine_parameters_number (ecma_builtin_global_detail_id_t routine_id); +ecma_builtin_global_get_routine_parameters_number (ecma_magic_string_id_t routine_id); extern ecma_completion_value_t -ecma_builtin_global_dispatch_routine (ecma_builtin_global_detail_id_t builtin_routine_id, +ecma_builtin_global_dispatch_routine (ecma_magic_string_id_t builtin_routine_id, ecma_value_t arguments_list [], ecma_length_t arguments_number); +extern ecma_property_t* +ecma_builtin_global_try_to_instantiate_property (ecma_object_t *obj_p, + ecma_string_t *prop_name_p); /* ecma-builtin-object-object.c */ extern void ecma_builtin_init_object_object (void); extern void ecma_builtin_finalize_object_object (void); +extern ecma_property_t* +ecma_builtin_object_try_to_instantiate_property (ecma_object_t *obj_p, + ecma_string_t *prop_name_p); + extern void ecma_builtin_init_object_prototype_object (void); extern void ecma_builtin_finalize_object_prototype_object (void); +extern ecma_property_t* +ecma_builtin_object_prototype_try_to_instantiate_property (ecma_object_t *obj_p, + ecma_string_t *prop_name_p); /* ecma-builtin-array-object.c */ extern void ecma_builtin_init_array_object (void); extern void ecma_builtin_finalize_array_object (void); +extern ecma_property_t* +ecma_builtin_array_try_to_instantiate_property (ecma_object_t *obj_p, + ecma_string_t *prop_name_p); + extern void ecma_builtin_init_array_prototype_object (void); extern void ecma_builtin_finalize_array_prototype_object (void); +extern ecma_property_t* +ecma_builtin_array_prototype_try_to_instantiate_property (ecma_object_t *obj_p, + ecma_string_t *prop_name_p); +extern int32_t +ecma_builtin_bin_search_for_magic_string_id_in_array (const ecma_magic_string_id_t ids[], + ecma_length_t array_length, + ecma_magic_string_id_t key); #endif /* !ECMA_BUILTINS_INTERNAL_H */ diff --git a/src/libecmabuiltins/ecma-builtins.c b/src/libecmabuiltins/ecma-builtins.c index cf115fd40..724a34c87 100644 --- a/src/libecmabuiltins/ecma-builtins.c +++ b/src/libecmabuiltins/ecma-builtins.c @@ -30,6 +30,15 @@ * @{ */ +static ecma_length_t +ecma_builtin_get_routine_parameters_number (ecma_builtin_id_t builtin_id, + ecma_magic_string_id_t routine_id); +static ecma_completion_value_t +ecma_builtin_dispatch_routine (ecma_builtin_id_t builtin_object_id, + ecma_magic_string_id_t builtin_routine_id, + ecma_value_t arguments_list [], + ecma_length_t arguments_number); + /** * Initialize ECMA built-in objects */ @@ -57,11 +66,60 @@ ecma_finalize_builtins (void) * NULL - otherwise. */ ecma_property_t* -ecma_object_try_to_get_non_instantiated_property (ecma_object_t *object_p, /**< object */ - ecma_string_t *string_p) /**< property's name */ +ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object */ + ecma_string_t *string_p) /**< property's name */ { - JERRY_UNIMPLEMENTED_REF_UNUSED_VARS (object_p, string_p); -} /* ecma_object_try_to_get_non_instantiated_property */ + JERRY_ASSERT (ecma_get_object_is_builtin (object_p)); + + ecma_property_t *built_in_id_prop_p = ecma_get_internal_property (object_p, + ECMA_INTERNAL_PROPERTY_BUILT_IN_ID); + ecma_builtin_id_t builtin_id = (ecma_builtin_id_t) built_in_id_prop_p->u.internal_property.value; + + switch (builtin_id) + { + case ECMA_BUILTIN_ID_GLOBAL: + { + JERRY_ASSERT (ecma_builtin_is_global_object (object_p)); + return ecma_builtin_global_try_to_instantiate_property (object_p, string_p); + } + + case ECMA_BUILTIN_ID_OBJECT: + case ECMA_BUILTIN_ID_OBJECT_PROTOTYPE: + case ECMA_BUILTIN_ID_FUNCTION: + case ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE: + case ECMA_BUILTIN_ID_ARRAY: + case ECMA_BUILTIN_ID_ARRAY_PROTOTYPE: + case ECMA_BUILTIN_ID_STRING: + case ECMA_BUILTIN_ID_STRING_PROTOTYPE: + case ECMA_BUILTIN_ID_BOOLEAN: + case ECMA_BUILTIN_ID_BOOLEAN_PROTOTYPE: + case ECMA_BUILTIN_ID_NUMBER: + case ECMA_BUILTIN_ID_NUMBER_PROTOTYPE: + case ECMA_BUILTIN_ID_DATE: + case ECMA_BUILTIN_ID_REGEXP: + case ECMA_BUILTIN_ID_REGEXP_PROTOTYPE: + case ECMA_BUILTIN_ID_ERROR: + case ECMA_BUILTIN_ID_ERROR_PROTOTYPE: + case ECMA_BUILTIN_ID_EVAL_ERROR: + case ECMA_BUILTIN_ID_RANGE_ERROR: + case ECMA_BUILTIN_ID_REFERENCE_ERROR: + case ECMA_BUILTIN_ID_SYNTAX_ERROR: + case ECMA_BUILTIN_ID_TYPE_ERROR: + case ECMA_BUILTIN_ID_SYNTAX_URI_ERROR: + case ECMA_BUILTIN_ID_MATH: + case ECMA_BUILTIN_ID_JSON: + { + JERRY_UNIMPLEMENTED (); + } + + case ECMA_BUILTIN_ID__COUNT: + { + JERRY_UNREACHABLE (); + } + } + + JERRY_UNREACHABLE (); +} /* ecma_builtin_try_to_instantiate_property */ /** * Construct a Function object for specified built-in routine @@ -74,13 +132,13 @@ ecma_object_t* ecma_builtin_make_function_object_for_routine (ecma_builtin_id_t builtin_id, /**< identifier of built-in object that initially contains property with the routine */ - uint32_t routine_id) /**< identifier of the built-in object's - routine property - (one of ecma_builtin_{*}_property_id_t) */ + ecma_magic_string_id_t routine_id) /**< name of the built-in + object's routine property */ { FIXME(Setup prototype of Function object to built-in Function prototype object (15.3.3.1)); ecma_object_t *func_obj_p = ecma_create_object (NULL, true, ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION); + ecma_set_object_is_builtin (func_obj_p, true); uint64_t packed_value = jrt_set_bit_field_value (0, builtin_id, @@ -96,55 +154,103 @@ ecma_builtin_make_function_object_for_routine (ecma_builtin_id_t builtin_id, /** JERRY_ASSERT ((uint32_t) packed_value == packed_value); routine_id_prop_p->u.internal_property.value = (uint32_t) packed_value; + ecma_string_t* magic_string_length_p = ecma_get_magic_string (ECMA_MAGIC_STRING_LENGTH); + ecma_property_t *len_prop_p = ecma_create_named_data_property (func_obj_p, + magic_string_length_p, + ECMA_PROPERTY_NOT_WRITABLE, + ECMA_PROPERTY_NOT_ENUMERABLE, + ECMA_PROPERTY_NOT_CONFIGURABLE); + + ecma_deref_ecma_string (magic_string_length_p); + ecma_number_t* len_p = ecma_alloc_number (); *len_p = ecma_uint32_to_number (ecma_builtin_get_routine_parameters_number (builtin_id, routine_id)); - ecma_property_descriptor_t length_prop_desc = ecma_make_empty_property_descriptor (); - length_prop_desc.is_value_defined = true; - length_prop_desc.value = ecma_make_number_value (len_p); - length_prop_desc.is_writable_defined = false; - length_prop_desc.writable = ECMA_PROPERTY_NOT_WRITABLE; - length_prop_desc.is_enumerable_defined = false; - length_prop_desc.enumerable = ECMA_PROPERTY_NOT_ENUMERABLE; - length_prop_desc.is_configurable_defined = false; - length_prop_desc.configurable = ECMA_PROPERTY_NOT_CONFIGURABLE; - - ecma_string_t* magic_string_length_p = ecma_get_magic_string (ECMA_MAGIC_STRING_LENGTH); - ecma_completion_value_t completion = ecma_op_object_define_own_property (func_obj_p, - magic_string_length_p, - length_prop_desc, - false); - ecma_deref_ecma_string (magic_string_length_p); - - JERRY_ASSERT (ecma_is_completion_value_normal_true (completion) - || ecma_is_completion_value_normal_false (completion)); - - ecma_dealloc_number (len_p); - len_p = NULL; + len_prop_p->u.named_data_property.value = ecma_make_number_value (len_p); return func_obj_p; } /* ecma_builtin_make_function_object_for_routine */ +/** + * Handle calling [[Call]] of built-in object + * + * @return completion-value + */ +ecma_completion_value_t +ecma_builtin_dispatch_call (ecma_object_t *obj_p, /**< built-in object */ + ecma_value_t *arguments_list_p, /**< arguments list */ + ecma_length_t arguments_list_len) /**< length of the arguments list */ +{ + JERRY_ASSERT (ecma_get_object_is_builtin (obj_p)); + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION) + { + ecma_property_t *id_prop_p = ecma_get_internal_property (obj_p, + ECMA_INTERNAL_PROPERTY_BUILT_IN_ROUTINE_ID); + uint64_t packed_built_in_and_routine_id = id_prop_p->u.internal_property.value; + + uint64_t built_in_id_field = jrt_extract_bit_field (packed_built_in_and_routine_id, + ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_OBJECT_ID_POS, + ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_OBJECT_ID_WIDTH); + JERRY_ASSERT (built_in_id_field < ECMA_BUILTIN_ID__COUNT); + + uint64_t routine_id_field = jrt_extract_bit_field (packed_built_in_and_routine_id, + ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_ROUTINE_ID_POS, + ECMA_BUILTIN_ROUTINE_ID_BUILT_IN_ROUTINE_ID_WIDTH); + JERRY_ASSERT (routine_id_field < ECMA_MAGIC_STRING__COUNT); + + ecma_builtin_id_t built_in_id = (ecma_builtin_id_t) built_in_id_field; + ecma_magic_string_id_t routine_id = (ecma_magic_string_id_t) routine_id_field; + + return ecma_builtin_dispatch_routine (built_in_id, + routine_id, + arguments_list_p, + arguments_list_len); + } + else + { + JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_FUNCTION); + + JERRY_UNIMPLEMENTED (); + } +} /* ecma_builtin_dispatch_call */ + +/** + * Handle calling [[Construct]] of built-in object + * + * @return completion-value + */ +ecma_completion_value_t +ecma_builtin_dispatch_construct (ecma_object_t *obj_p, /**< built-in object */ + ecma_value_t *arguments_list_p, /**< arguments list */ + ecma_length_t arguments_list_len) /**< length of the arguments list */ +{ + JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_FUNCTION); + + JERRY_ASSERT (ecma_get_object_is_builtin (obj_p)); + JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); + + JERRY_UNIMPLEMENTED_REF_UNUSED_VARS (obj_p, arguments_list_p, arguments_list_len); +} /* ecma_builtin_dispatch_construct */ + /** * Get parameters number of the built-in routine * * @return number of parameters of the routine according to ECMA-262 v5 specification */ -ecma_length_t +static ecma_length_t ecma_builtin_get_routine_parameters_number (ecma_builtin_id_t builtin_id, /**< identifier of built-in object that initially contains property with the routine */ - uint32_t routine_id) /**< identifier of the built-in object's - routine property - (one of ecma_builtin_{*}_property_id_t) */ + ecma_magic_string_id_t routine_id) /**< name of the built-in object's + routine property */ { switch (builtin_id) { case ECMA_BUILTIN_ID_GLOBAL: { - JERRY_ASSERT (routine_id < ECMA_BUILTIN_GLOBAL_DETAIL_ID__COUNT); - - return ecma_builtin_global_get_routine_parameters_number ((ecma_builtin_global_detail_id_t) routine_id); + return ecma_builtin_global_get_routine_parameters_number (routine_id); } case ECMA_BUILTIN_ID_OBJECT: case ECMA_BUILTIN_ID_OBJECT_PROTOTYPE: @@ -174,6 +280,11 @@ ecma_builtin_get_routine_parameters_number (ecma_builtin_id_t builtin_id, /**< i { JERRY_UNIMPLEMENTED_REF_UNUSED_VARS (routine_id); } + + case ECMA_BUILTIN_ID__COUNT: + { + JERRY_UNREACHABLE (); + } } JERRY_UNREACHABLE (); @@ -185,10 +296,10 @@ ecma_builtin_get_routine_parameters_number (ecma_builtin_id_t builtin_id, /**< i * @return completion-value * Returned value must be freed with ecma_free_completion_value. */ -ecma_completion_value_t +static ecma_completion_value_t ecma_builtin_dispatch_routine (ecma_builtin_id_t builtin_object_id, /**< built-in object' identifier */ - uint32_t builtin_routine_id, /**< identifier of the built-in object's routine - property (one of ecma_builtin_{*}_property_id_t) */ + ecma_magic_string_id_t builtin_routine_id, /**< name of the built-in object's + routine property */ ecma_value_t arguments_list [], /**< list of arguments passed to routine */ ecma_length_t arguments_number) /**< length of arguments' list */ { @@ -196,9 +307,7 @@ ecma_builtin_dispatch_routine (ecma_builtin_id_t builtin_object_id, /**< built-i { case ECMA_BUILTIN_ID_GLOBAL: { - JERRY_ASSERT (builtin_routine_id < ECMA_BUILTIN_GLOBAL_DETAIL_ID__COUNT); - - return ecma_builtin_global_dispatch_routine ((ecma_builtin_global_detail_id_t) builtin_routine_id, + return ecma_builtin_global_dispatch_routine (builtin_routine_id, arguments_list, arguments_number); } @@ -232,11 +341,67 @@ ecma_builtin_dispatch_routine (ecma_builtin_id_t builtin_object_id, /**< built-i arguments_list, arguments_number); } + + case ECMA_BUILTIN_ID__COUNT: + { + JERRY_UNREACHABLE (); + } } JERRY_UNREACHABLE (); } /* ecma_builtin_dispatch_routine */ +/** + * Binary search for magic string identifier in array. + * + * Warning: + * array should be sorted in ascending order + * + * @return index of identifier, if it is contained in array, + * -1 - otherwise. + */ +int32_t +ecma_builtin_bin_search_for_magic_string_id_in_array (const ecma_magic_string_id_t ids[], /**< array to search in */ + ecma_length_t array_length, /**< number of elements + in the array */ + ecma_magic_string_id_t key) /**< value to search for */ +{ +#ifndef JERRY_NDEBUG + /* For binary search the values should be sorted */ + for (ecma_length_t id_index = 1; + id_index < array_length; + id_index++) + { + JERRY_ASSERT (ids [id_index - 1] < ids [id_index]); + } +#endif /* !JERRY_NDEBUG */ + + int32_t min = 0; + int32_t max = array_length - 1; + + while (min <= max) + { + int32_t mid = (min + max) / 2; + + if (ids[mid] == key) + { + return mid; + } + else if (ids[mid] > key) + { + max = mid - 1; + } + else + { + JERRY_ASSERT (ids[mid] < key); + + min = mid + 1; + } + } + + return -1; +} /* ecma_builtin_bin_search_for_magic_string_id_in_array */ + /** * @} * @} diff --git a/src/libecmabuiltins/ecma-builtins.h b/src/libecmabuiltins/ecma-builtins.h index 78fabf23a..fe259b3db 100644 --- a/src/libecmabuiltins/ecma-builtins.h +++ b/src/libecmabuiltins/ecma-builtins.h @@ -22,9 +22,17 @@ extern void ecma_init_builtins (void); extern void ecma_finalize_builtins (void); +extern ecma_completion_value_t +ecma_builtin_dispatch_call (ecma_object_t *obj_p, + ecma_value_t *arguments_list_p, + ecma_length_t arguments_list_len); +extern ecma_completion_value_t +ecma_builtin_dispatch_construct (ecma_object_t *obj_p, + ecma_value_t *arguments_list_p, + ecma_length_t arguments_list_len); extern ecma_property_t* -ecma_object_try_to_get_non_instantiated_property (ecma_object_t *object_p, - ecma_string_t *string_p); +ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, + ecma_string_t *string_p); /* ecma-builtin-global.c */ extern ecma_object_t* ecma_builtin_get_global_object (void); diff --git a/src/libecmaobjects/ecma-gc.c b/src/libecmaobjects/ecma-gc.c index b738ae914..9126d5080 100644 --- a/src/libecmaobjects/ecma-gc.c +++ b/src/libecmaobjects/ecma-gc.c @@ -408,7 +408,10 @@ ecma_gc_mark (ecma_object_t *object_p, /**< start object */ case ECMA_INTERNAL_PROPERTY_PROVIDE_THIS: /* a boolean */ case ECMA_INTERNAL_PROPERTY_CLASS: /* an enum */ case ECMA_INTERNAL_PROPERTY_CODE: /* an integer */ + case ECMA_INTERNAL_PROPERTY_BUILT_IN_ID: /* an integer */ case ECMA_INTERNAL_PROPERTY_BUILT_IN_ROUTINE_ID: /* an integer */ + case ECMA_INTERNAL_PROPERTY_NON_INSTANTIATED_BUILT_IN_MASK_0_31: /* an integer (bit-mask) */ + case ECMA_INTERNAL_PROPERTY_NON_INSTANTIATED_BUILT_IN_MASK_32_63: /* an integer (bit-mask) */ { break; } diff --git a/src/libecmaobjects/ecma-globals.h b/src/libecmaobjects/ecma-globals.h index 031be9c43..a4936539b 100644 --- a/src/libecmaobjects/ecma-globals.h +++ b/src/libecmaobjects/ecma-globals.h @@ -196,10 +196,23 @@ typedef enum /** Part of an array, that is indexed by strings */ ECMA_INTERNAL_PROPERTY_STRING_INDEXED_ARRAY_VALUES, + /** Implementation-defined identifier of built-in object */ + ECMA_INTERNAL_PROPERTY_BUILT_IN_ID, + /** Implementation-defined identifier of built-in routine that corresponds to a built-in function object ([[Built-in routine ID]]) */ - ECMA_INTERNAL_PROPERTY_BUILT_IN_ROUTINE_ID + ECMA_INTERNAL_PROPERTY_BUILT_IN_ROUTINE_ID, + + /** + * Bit-mask of non-instantiated built-in's properties (bits 0-31) + */ + ECMA_INTERNAL_PROPERTY_NON_INSTANTIATED_BUILT_IN_MASK_0_31, + + /** + * Bit-mask of non-instantiated built-in's properties (bits 32-63) + */ + ECMA_INTERNAL_PROPERTY_NON_INSTANTIATED_BUILT_IN_MASK_32_63, } ecma_internal_property_id_t; /** diff --git a/src/libecmaobjects/ecma-helpers.c b/src/libecmaobjects/ecma-helpers.c index 447ba3e7f..ee50061c6 100644 --- a/src/libecmaobjects/ecma-helpers.c +++ b/src/libecmaobjects/ecma-helpers.c @@ -663,7 +663,10 @@ ecma_free_internal_property (ecma_property_t *property_p) /**< the property */ case ECMA_INTERNAL_PROPERTY_PROVIDE_THIS: /* a boolean */ case ECMA_INTERNAL_PROPERTY_CLASS: /* an enum */ case ECMA_INTERNAL_PROPERTY_CODE: /* an integer */ + case ECMA_INTERNAL_PROPERTY_BUILT_IN_ID: /* an integer */ case ECMA_INTERNAL_PROPERTY_BUILT_IN_ROUTINE_ID: /* an integer */ + case ECMA_INTERNAL_PROPERTY_NON_INSTANTIATED_BUILT_IN_MASK_0_31: /* an integer (bit-mask) */ + case ECMA_INTERNAL_PROPERTY_NON_INSTANTIATED_BUILT_IN_MASK_32_63: /* an integer (bit-mask) */ { break; } diff --git a/src/libecmaoperations/ecma-function-object.c b/src/libecmaoperations/ecma-function-object.c index b7e7d8255..398ac8a0d 100644 --- a/src/libecmaoperations/ecma-function-object.c +++ b/src/libecmaoperations/ecma-function-object.c @@ -124,8 +124,7 @@ ecma_is_constructor (ecma_value_t value) /**< ecma-value */ JERRY_ASSERT(!ecma_is_lexical_environment (obj_p)); return (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_FUNCTION - || ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION - || ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION); + || ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION); } /* ecma_is_constructor */ /** @@ -448,6 +447,11 @@ ecma_op_function_call (ecma_object_t *func_obj_p, /**< Function object */ if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION) { + if (unlikely (ecma_get_object_is_builtin (func_obj_p))) + { + return ecma_builtin_dispatch_call (func_obj_p, arguments_list_p, arguments_list_len); + } + ecma_completion_value_t ret_value; /* Entering Function Code (ECMA-262 v5, 10.4.3) */ @@ -520,7 +524,7 @@ ecma_op_function_call (ecma_object_t *func_obj_p, /**< Function object */ } else if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION) { - JERRY_UNIMPLEMENTED (); + return ecma_builtin_dispatch_call (func_obj_p, arguments_list_p, arguments_list_len); } else { @@ -545,11 +549,16 @@ ecma_op_function_construct (ecma_object_t *func_obj_p, /**< Function object */ { JERRY_ASSERT(func_obj_p != NULL && !ecma_is_lexical_environment (func_obj_p)); - JERRY_ASSERT(ecma_op_is_callable (ecma_make_object_value (func_obj_p))); + JERRY_ASSERT(ecma_is_constructor (ecma_make_object_value (func_obj_p))); JERRY_ASSERT(arguments_list_len == 0 || arguments_list_p != NULL); if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION) { + if (unlikely (ecma_get_object_is_builtin (func_obj_p))) + { + return ecma_builtin_dispatch_construct (func_obj_p, arguments_list_p, arguments_list_len); + } + ecma_completion_value_t ret_value; ecma_string_t *prototype_magic_string_p = ecma_get_magic_string (ECMA_MAGIC_STRING_PROTOTYPE); @@ -614,10 +623,6 @@ ecma_op_function_construct (ecma_object_t *func_obj_p, /**< Function object */ return ret_value; } - else if (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION) - { - JERRY_UNIMPLEMENTED (); - } else { JERRY_ASSERT(ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION); diff --git a/src/libecmaoperations/ecma-objects.c b/src/libecmaoperations/ecma-objects.c index 4888d75c6..f8f00bee1 100644 --- a/src/libecmaoperations/ecma-objects.c +++ b/src/libecmaoperations/ecma-objects.c @@ -53,6 +53,7 @@ ecma_op_object_get (ecma_object_t *obj_p, /**< the object */ case ECMA_OBJECT_TYPE_GENERAL: case ECMA_OBJECT_TYPE_ARRAY: case ECMA_OBJECT_TYPE_STRING: + case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION: { return ecma_op_general_object_get (obj_p, property_name_p); } @@ -64,7 +65,6 @@ ecma_op_object_get (ecma_object_t *obj_p, /**< the object */ case ECMA_OBJECT_TYPE_BOUND_FUNCTION: case ECMA_OBJECT_TYPE_FUNCTION: - case ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION: { return ecma_op_function_object_get (obj_p, property_name_p); } @@ -129,9 +129,10 @@ ecma_op_object_get_own_property (ecma_object_t *obj_p, /**< the object */ if (unlikely (prop_p == NULL)) { - if (is_builtin) + if (is_builtin + && type != ECMA_OBJECT_TYPE_BUILT_IN_FUNCTION) { - prop_p = ecma_object_try_to_get_non_instantiated_property (obj_p, property_name_p); + prop_p = ecma_builtin_try_to_instantiate_property (obj_p, property_name_p); } }