diff --git a/jerry-core/api/jerry.c b/jerry-core/api/jerry.c index 8304177e3..74f7bbe6f 100644 --- a/jerry-core/api/jerry.c +++ b/jerry-core/api/jerry.c @@ -1740,18 +1740,19 @@ jerry_get_array_length (const jerry_value_t value) /**< api value */ { jerry_assert_api_available (); - if (!jerry_value_is_array (value)) + if (!jerry_value_is_object (value)) { return 0; } - ecma_value_t len_value = ecma_op_object_get_by_magic_id (ecma_get_object_from_value (value), - LIT_MAGIC_STRING_LENGTH); + ecma_object_t *object_p = ecma_get_object_from_value (value); - jerry_length_t length = ecma_number_to_uint32 (ecma_get_number_from_value (len_value)); - ecma_free_value (len_value); + if (JERRY_LIKELY (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_ARRAY)) + { + return ecma_array_get_length (object_p); + } - return length; + return 0; } /* jerry_get_array_length */ /** @@ -2217,9 +2218,7 @@ jerry_get_property_by_index (const jerry_value_t obj_val, /**< object value */ return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p))); } - ecma_string_t *str_idx_p = ecma_new_ecma_string_from_uint32 (index); - ecma_value_t ret_value = ecma_op_object_get (ecma_get_object_from_value (obj_val), str_idx_p); - ecma_deref_ecma_string (str_idx_p); + ecma_value_t ret_value = ecma_op_object_get_by_uint32_index (ecma_get_object_from_value (obj_val), index); return jerry_return (ret_value); } /* jerry_get_property_by_index */ @@ -2325,12 +2324,10 @@ jerry_set_property_by_index (const jerry_value_t obj_val, /**< object value */ return jerry_throw (ecma_raise_type_error (ECMA_ERR_MSG (wrong_args_msg_p))); } - ecma_string_t *str_idx_p = ecma_new_ecma_string_from_uint32 ((uint32_t) index); - ecma_value_t ret_value = ecma_op_object_put (ecma_get_object_from_value (obj_val), - str_idx_p, - value_to_set, - true); - ecma_deref_ecma_string (str_idx_p); + ecma_value_t ret_value = ecma_op_object_put_by_uint32_index (ecma_get_object_from_value (obj_val), + index, + value_to_set, + true); return jerry_return (ret_value); } /* jerry_set_property_by_index */ diff --git a/jerry-core/debugger/debugger.c b/jerry-core/debugger/debugger.c index 7fe458baf..1f56bea41 100644 --- a/jerry-core/debugger/debugger.c +++ b/jerry-core/debugger/debugger.c @@ -304,7 +304,7 @@ jerry_debugger_get_variable_type (ecma_value_t value) /**< input ecma value */ { JERRY_ASSERT (ecma_is_value_object (value)); - if (ecma_object_get_class_name (ecma_get_object_from_value (value)) == LIT_MAGIC_STRING_ARRAY_UL) + if (ecma_get_object_type (ecma_get_object_from_value (value)) == ECMA_OBJECT_TYPE_ARRAY) { ret_value = JERRY_DEBUGGER_VALUE_ARRAY; } diff --git a/jerry-core/ecma/base/ecma-globals.h b/jerry-core/ecma/base/ecma-globals.h index 7f22ef0bd..a123bad79 100644 --- a/jerry-core/ecma/base/ecma-globals.h +++ b/jerry-core/ecma/base/ecma-globals.h @@ -602,15 +602,15 @@ typedef enum { ECMA_OBJECT_TYPE_GENERAL = 0, /**< all objects that are not belongs to the sub-types below. */ ECMA_OBJECT_TYPE_CLASS = 1, /**< Objects with class property */ - ECMA_OBJECT_TYPE_FUNCTION = 2, /**< Function objects (15.3), created through 13.2 routine */ - ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION = 3, /**< External (host) function object */ - ECMA_OBJECT_TYPE_ARRAY = 4, /**< Array object (15.4) */ - ECMA_OBJECT_TYPE_BOUND_FUNCTION = 5, /**< Function objects (15.3), created through 15.3.4.5 routine */ - ECMA_OBJECT_TYPE_PSEUDO_ARRAY = 6, /**< Array-like object, such as Arguments object (10.6) */ + ECMA_OBJECT_TYPE_ARRAY = 2, /**< Array object (15.4) */ + ECMA_OBJECT_TYPE_PSEUDO_ARRAY = 3, /**< Array-like object, such as Arguments object (10.6) */ + /* Note: these 4 types must be in this order. See IsCallable operation. */ + ECMA_OBJECT_TYPE_FUNCTION = 4, /**< Function objects (15.3), created through 13.2 routine */ #if ENABLED (JERRY_ES2015) - ECMA_OBJECT_TYPE_ARROW_FUNCTION = 7, /**< arrow function objects */ + ECMA_OBJECT_TYPE_ARROW_FUNCTION = 5, /**< arrow function objects */ #endif /* ENABLED (JERRY_ES2015) */ - + ECMA_OBJECT_TYPE_BOUND_FUNCTION = 6, /**< Function objects (15.3), created through 15.3.4.5 routine */ + ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION = 7, /**< External (host) function object */ /* Types between 13-15 cannot have a built-in flag. See ecma_lexical_environment_type_t. */ ECMA_OBJECT_TYPE__MAX /**< maximum value */ 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 c678d7640..9044c8bea 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 @@ -78,40 +78,14 @@ ecma_builtin_array_iterator_prototype_object_next (ecma_value_t this_val) /**< t ecma_object_t *array_object_p = ecma_get_object_from_value (iterated_value); - uint32_t length; - /* 8 - 9. */ -#if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) - if (ecma_is_typedarray (ecma_make_object_value (array_object_p))) + uint32_t length; + ecma_value_t len_value = ecma_op_object_get_length (array_object_p, &length); + + if (ECMA_IS_VALUE_ERROR (len_value)) { - length = ecma_typedarray_get_length (array_object_p); + return len_value; } - else - { -#endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */ - ecma_value_t len_value = ecma_op_object_get (array_object_p, - ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH)); - - if (ECMA_IS_VALUE_ERROR (len_value)) - { - return len_value; - } - - ecma_number_t length_number; - ecma_value_t length_value = ecma_get_number (len_value, &length_number); - - if (ECMA_IS_VALUE_ERROR (length_value)) - { - ecma_free_value (len_value); - return length_value; - } - - length = ecma_number_to_uint32 (length_number); - - ecma_free_value (len_value); -#if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) - } -#endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */ uint32_t index = ext_obj_p->u.pseudo_array.u1.iterator_index; @@ -157,12 +131,8 @@ ecma_builtin_array_iterator_prototype_object_next (ecma_value_t this_val) /**< t return ecma_create_iter_result_object (ecma_make_uint32_value (index), ECMA_VALUE_FALSE); } - /* 13. */ - ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index); - /* 14. */ - ecma_value_t get_value = ecma_op_object_get (array_object_p, index_string_p); - ecma_deref_ecma_string (index_string_p); + ecma_value_t get_value = ecma_op_object_get_by_uint32_index (array_object_p, index); /* 15. */ if (ECMA_IS_VALUE_ERROR (get_value)) 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 8799e0093..48bbcc949 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.c @@ -176,14 +176,13 @@ ecma_builtin_array_prototype_object_to_locale_string (ecma_object_t *obj_p, /**< } /* 7-8. */ - ecma_value_t first_value = ecma_builtin_helper_get_to_locale_string_at_index (obj_p, 0); + ecma_string_t *first_string_p = ecma_builtin_helper_get_to_locale_string_at_index (obj_p, 0); - if (ECMA_IS_VALUE_ERROR (first_value)) + if (JERRY_UNLIKELY (first_string_p == NULL)) { - return first_value; + return ECMA_VALUE_ERROR; } - ecma_string_t *first_string_p = ecma_get_string_from_value (first_value); ecma_stringbuilder_t builder = ecma_stringbuilder_create_from (first_string_p); ecma_deref_ecma_string (first_string_p); @@ -193,15 +192,14 @@ ecma_builtin_array_prototype_object_to_locale_string (ecma_object_t *obj_p, /**< /* 4. Implementation-defined: set the separator to a single comma character. */ ecma_stringbuilder_append_byte (&builder, LIT_CHAR_COMMA); - ecma_value_t next_string_value = ecma_builtin_helper_get_to_locale_string_at_index (obj_p, k); + ecma_string_t *next_string_p = ecma_builtin_helper_get_to_locale_string_at_index (obj_p, k); - if (ECMA_IS_VALUE_ERROR (next_string_value)) + if (JERRY_UNLIKELY (next_string_p == NULL)) { ecma_stringbuilder_destroy (&builder); - return next_string_value; + return ECMA_VALUE_ERROR; } - ecma_string_t *next_string_p = ecma_get_string_from_value (next_string_value); ecma_stringbuilder_append (&builder, next_string_p); ecma_deref_ecma_string (next_string_p); } @@ -310,11 +308,7 @@ static ecma_string_t * ecma_op_array_get_to_string_at_index (ecma_object_t *obj_p, /**< this object */ uint32_t index) /**< array index */ { - ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index); - - ecma_value_t index_value = ecma_op_object_get (obj_p, index_string_p); - - ecma_deref_ecma_string (index_string_p); + ecma_value_t index_value = ecma_op_object_get_by_uint32_index (obj_p, index); if (ECMA_IS_VALUE_ERROR (index_value)) { @@ -422,15 +416,12 @@ ecma_builtin_array_prototype_object_pop (ecma_object_t *obj_p, /**< array object return ECMA_IS_VALUE_ERROR (set_length_value) ? set_length_value : ECMA_VALUE_UNDEFINED; } - /* 5.a */ - ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (--len); - /* 5.b */ - ecma_value_t get_value = ecma_op_object_get (obj_p, index_str_p); + len--; + ecma_value_t get_value = ecma_op_object_get_by_uint32_index (obj_p, len); if (ECMA_IS_VALUE_ERROR (get_value)) { - ecma_deref_ecma_string (index_str_p); return get_value; } @@ -448,9 +439,7 @@ ecma_builtin_array_prototype_object_pop (ecma_object_t *obj_p, /**< array object } /* 5.c */ - ecma_value_t del_value = ecma_op_object_delete (obj_p, index_str_p, true); - - ecma_deref_ecma_string (index_str_p); + ecma_value_t del_value = ecma_op_object_delete_by_uint32_index (obj_p, len, true); if (ECMA_IS_VALUE_ERROR (del_value)) { @@ -684,7 +673,7 @@ ecma_builtin_array_prototype_object_shift (ecma_object_t *obj_p, /**< array obje } /* 5. */ - ecma_value_t first_value = ecma_op_object_get (obj_p, ecma_get_ecma_string_from_uint32 (0)); + ecma_value_t first_value = ecma_op_object_get_by_uint32_index (obj_p, 0); if (ECMA_IS_VALUE_ERROR (first_value)) { @@ -2227,7 +2216,8 @@ ecma_builtin_array_prototype_dispatch_routine (uint16_t builtin_routine_id, /**< } #endif /* ENABLED (JERRY_ES2015_BUILTIN_ITERATOR) */ - ecma_value_t len_value = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_LENGTH); + uint32_t length; + ecma_value_t len_value = ecma_op_object_get_length (obj_p, &length); if (ECMA_IS_VALUE_ERROR (len_value)) { @@ -2235,16 +2225,7 @@ ecma_builtin_array_prototype_dispatch_routine (uint16_t builtin_routine_id, /**< return len_value; } - uint32_t length = 0; - ecma_value_t ret_value = ecma_op_to_length (len_value, &length); - - if (ECMA_IS_VALUE_ERROR (ret_value)) - { - ecma_free_value (len_value); - ecma_deref_object (obj_p); - return ret_value; - } - + ecma_value_t ret_value; ecma_value_t routine_arg_1 = arguments_list_p[0]; ecma_value_t routine_arg_2 = arguments_list_p[1]; diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-array.c b/jerry-core/ecma/builtin-objects/ecma-builtin-array.c index deb16d62b..7e58f3201 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-array.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-array.c @@ -58,19 +58,16 @@ ecma_builtin_array_object_is_array (ecma_value_t this_arg, /**< 'this' argument ecma_value_t arg) /**< first argument */ { JERRY_UNUSED (this_arg); - ecma_value_t is_array = ECMA_VALUE_FALSE; if (ecma_is_value_object (arg)) { - ecma_object_t *obj_p = ecma_get_object_from_value (arg); - - if (ecma_object_get_class_name (obj_p) == LIT_MAGIC_STRING_ARRAY_UL) + if (ecma_get_object_type (ecma_get_object_from_value (arg)) == ECMA_OBJECT_TYPE_ARRAY) { - is_array = ECMA_VALUE_TRUE; + return ECMA_VALUE_TRUE; } } - return is_array; + return ECMA_VALUE_FALSE; } /* ecma_builtin_array_object_is_array */ /** 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 95afa332f..6dac5c681 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.c @@ -112,27 +112,15 @@ ecma_builtin_function_prototype_object_apply (ecma_object_t *func_obj_p, /**< th ecma_object_t *obj_p = ecma_get_object_from_value (arg2); - /* 4. */ - ecma_value_t length_value = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_LENGTH); - if (ECMA_IS_VALUE_ERROR (length_value)) + /* 4-5. */ + uint32_t length; + ecma_value_t len_value = ecma_op_object_get_length (obj_p, &length); + + if (ECMA_IS_VALUE_ERROR (len_value)) { - return length_value; + return len_value; } - ecma_number_t length_number; - ecma_value_t get_result = ecma_get_number (length_value, &length_number); - - ecma_free_value (length_value); - - if (ECMA_IS_VALUE_ERROR (get_result)) - { - return get_result; - } - JERRY_ASSERT (ecma_is_value_empty (get_result)); - - /* 5. */ - const uint32_t length = ecma_number_to_uint32 (length_number); - if (length >= ECMA_FUNCTION_APPLY_ARGUMENT_COUNT_LIMIT) { return ecma_raise_range_error (ECMA_ERR_MSG ("Too many arguments declared for Function.apply().")); @@ -146,9 +134,7 @@ ecma_builtin_function_prototype_object_apply (ecma_object_t *func_obj_p, /**< th /* 7. */ for (index = 0; index < length; index++) { - ecma_string_t *curr_idx_str_p = ecma_new_ecma_string_from_uint32 (index); - ecma_value_t get_value = ecma_op_object_get (obj_p, curr_idx_str_p); - ecma_deref_ecma_string (curr_idx_str_p); + ecma_value_t get_value = ecma_op_object_get_by_uint32_index (obj_p, index); if (ECMA_IS_VALUE_ERROR (get_value)) { diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.c b/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.c index a1d18b6ce..428656a0f 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.c @@ -201,80 +201,67 @@ ecma_builtin_helper_object_to_string (const ecma_value_t this_arg) /**< this arg * @return ecma value * Returned value must be freed with ecma_free_value. */ -ecma_value_t +ecma_string_t * ecma_builtin_helper_get_to_locale_string_at_index (ecma_object_t *obj_p, /**< this object */ uint32_t index) /**< array index */ { - ecma_value_t ret_value = ECMA_VALUE_EMPTY; - ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index); - ecma_value_t index_value = ecma_op_object_get (obj_p, index_string_p); - ecma_deref_ecma_string (index_string_p); + ecma_value_t index_value = ecma_op_object_get_by_uint32_index (obj_p, index); if (ECMA_IS_VALUE_ERROR (index_value)) { - return index_value; + return NULL; } if (ecma_is_value_undefined (index_value) || ecma_is_value_null (index_value)) { - ecma_free_value (index_value); - return ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); + return ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); } ecma_value_t index_obj_value = ecma_op_to_object (index_value); - ecma_free_value (index_value); if (ECMA_IS_VALUE_ERROR (index_obj_value)) { - return index_obj_value; + ecma_free_value (index_value); + return NULL; } + ecma_string_t *ret_string_p = NULL; ecma_object_t *index_obj_p = ecma_get_object_from_value (index_obj_value); ecma_value_t to_locale_value = ecma_op_object_get_by_magic_id (index_obj_p, LIT_MAGIC_STRING_TO_LOCALE_STRING_UL); if (ECMA_IS_VALUE_ERROR (to_locale_value)) { - ecma_deref_object (index_obj_p); - return to_locale_value; + goto cleanup; } - if (ecma_op_is_callable (to_locale_value)) - { - ecma_object_t *locale_func_obj_p = ecma_get_object_from_value (to_locale_value); - - ecma_value_t call_value = ecma_op_function_call (locale_func_obj_p, - ecma_make_object_value (index_obj_p), - NULL, - 0); - - ecma_deref_object (locale_func_obj_p); - ecma_deref_object (index_obj_p); - - if (ECMA_IS_VALUE_ERROR (call_value)) - { - return call_value; - } - - ecma_string_t *call_str_p = ecma_op_to_string (call_value); - - ecma_free_value (call_value); - - if (JERRY_UNLIKELY (call_str_p == NULL)) - { - return ECMA_VALUE_ERROR; - } - - ret_value = ecma_make_string_value (call_str_p); - } - else + if (!ecma_op_is_callable (to_locale_value)) { ecma_free_value (to_locale_value); - ecma_deref_object (index_obj_p); - ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("'toLocaleString' is missing or not a function.")); + ecma_raise_type_error (ECMA_ERR_MSG ("'toLocaleString' is missing or not a function.")); + goto cleanup; } - return ret_value; + ecma_object_t *locale_func_obj_p = ecma_get_object_from_value (to_locale_value); + ecma_value_t call_value = ecma_op_function_call (locale_func_obj_p, + index_obj_value, + NULL, + 0); + ecma_deref_object (locale_func_obj_p); + + if (ECMA_IS_VALUE_ERROR (call_value)) + { + goto cleanup; + } + + ret_string_p = ecma_op_to_string (call_value); + ecma_free_value (call_value); + +cleanup: + ecma_deref_object (index_obj_p); + ecma_free_value (index_value); + + return ret_string_p; } /* ecma_builtin_helper_get_to_locale_string_at_index */ @@ -423,80 +410,61 @@ ecma_builtin_helper_array_index_normalize (ecma_number_t index, /**< index */ * Returned value must be freed with ecma_free_value. */ ecma_value_t -ecma_builtin_helper_array_concat_value (ecma_object_t *obj_p, /**< array */ +ecma_builtin_helper_array_concat_value (ecma_object_t *array_obj_p, /**< array */ uint32_t *length_p, /**< [in,out] array's length */ ecma_value_t value) /**< value to concat */ { - ecma_value_t ret_value = ECMA_VALUE_EMPTY; - /* 5.b */ - if (ecma_is_value_object (value) - && (ecma_object_get_class_name (ecma_get_object_from_value (value)) == LIT_MAGIC_STRING_ARRAY_UL)) + if (ecma_is_value_object (value)) { - /* 5.b.ii */ - ECMA_TRY_CATCH (arg_len_value, - ecma_op_object_get_by_magic_id (ecma_get_object_from_value (value), - LIT_MAGIC_STRING_LENGTH), - ret_value); - ECMA_OP_TO_NUMBER_TRY_CATCH (arg_len_number, arg_len_value, ret_value); + ecma_object_t *obj_p = ecma_get_object_from_value (value); - uint32_t arg_len = ecma_number_to_uint32 (arg_len_number); - - /* 5.b.iii */ - for (uint32_t array_index = 0; - array_index < arg_len && ecma_is_value_empty (ret_value); - array_index++) + if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_ARRAY) { - ecma_string_t *array_index_string_p = ecma_new_ecma_string_from_uint32 (array_index); + /* 5.b.ii */ + uint32_t arg_len = ecma_array_get_length (obj_p); - /* 5.b.iii.2 */ - ECMA_TRY_CATCH (get_value, - ecma_op_object_find (ecma_get_object_from_value (value), - array_index_string_p), - ret_value); - - if (ecma_is_value_found (get_value)) + /* 5.b.iii */ + for (uint32_t array_index = 0; array_index < arg_len; array_index++) { - /* 5.b.iii.3.a */ - ecma_string_t *new_array_index_string_p = ecma_new_ecma_string_from_uint32 (*length_p + array_index); + /* 5.b.iii.2 */ + ecma_value_t get_value = ecma_op_object_find_by_uint32_index (obj_p, array_index); + + if (ECMA_IS_VALUE_ERROR (get_value)) + { + return get_value; + } + + if (!ecma_is_value_found (get_value)) + { + continue; + } /* 5.b.iii.3.b */ /* This will always be a simple value since 'is_throw' is false, so no need to free. */ - ecma_value_t put_comp = ecma_builtin_helper_def_prop (obj_p, - new_array_index_string_p, - get_value, - ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + ecma_value_t put_comp = ecma_builtin_helper_def_prop_by_index (array_obj_p, + *length_p + array_index, + get_value, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); JERRY_ASSERT (ecma_is_value_true (put_comp)); - ecma_deref_ecma_string (new_array_index_string_p); + ecma_free_value (get_value); } - ECMA_FINALIZE (get_value); - - ecma_deref_ecma_string (array_index_string_p); + *length_p += arg_len; + return ECMA_VALUE_EMPTY; } - - *length_p += arg_len; - - ECMA_OP_TO_NUMBER_FINALIZE (arg_len_number); - ECMA_FINALIZE (arg_len_value); - } - else - { - ecma_string_t *new_array_index_string_p = ecma_new_ecma_string_from_uint32 ((*length_p)++); - - /* 5.c.i */ - /* This will always be a simple value since 'is_throw' is false, so no need to free. */ - ecma_value_t put_comp = ecma_builtin_helper_def_prop (obj_p, - new_array_index_string_p, - value, - ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); - JERRY_ASSERT (ecma_is_value_true (put_comp)); - - ecma_deref_ecma_string (new_array_index_string_p); } - return ret_value; + /* 5.c.i */ + /* This will always be a simple value since 'is_throw' is false, so no need to free. */ + ecma_value_t put_comp = ecma_builtin_helper_def_prop_by_index (array_obj_p, + (*length_p)++, + value, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + JERRY_ASSERT (ecma_is_value_true (put_comp)); + + return ECMA_VALUE_EMPTY; } /* ecma_builtin_helper_array_concat_value */ /** diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.h b/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.h index 319811a80..5e8327396 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.h @@ -41,7 +41,7 @@ typedef enum ecma_value_t ecma_builtin_helper_object_to_string (const ecma_value_t this_arg); -ecma_value_t +ecma_string_t * ecma_builtin_helper_get_to_locale_string_at_index (ecma_object_t *obj_p, uint32_t index); ecma_value_t ecma_builtin_helper_object_get_properties (ecma_object_t *obj_p, uint32_t opts); diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-json.c b/jerry-core/ecma/builtin-objects/ecma-builtin-json.c index 6b47b9757..32a8ac4bf 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-json.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-json.c @@ -571,13 +571,12 @@ ecma_builtin_json_parse_value (ecma_json_token_t *token_p) /**< token argument * break; } - ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (length); - ecma_value_t completion = ecma_builtin_helper_def_prop (array_p, - index_str_p, - value, - ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + ecma_value_t completion; + completion = ecma_builtin_helper_def_prop_by_index (array_p, + length, + value, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); JERRY_ASSERT (ecma_is_value_true (completion)); - ecma_deref_ecma_string (index_str_p); ecma_free_value (value); ecma_builtin_json_parse_next_token (token_p, false); @@ -1255,11 +1254,10 @@ ecma_builtin_json_serialize_property (ecma_json_stringify_context_t *context_p, if (ecma_is_value_object (value) && !ecma_op_is_callable (value)) { ecma_object_t *obj_p = ecma_get_object_from_value (value); - lit_magic_string_id_t class_name = ecma_object_get_class_name (obj_p); ecma_value_t ret_value; /* 10.a */ - if (class_name == LIT_MAGIC_STRING_ARRAY_UL) + if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_ARRAY) { ret_value = ecma_builtin_json_serialize_array (context_p, obj_p); } @@ -1373,7 +1371,7 @@ ecma_builtin_json_stringify (ecma_value_t this_arg, /**< 'this' argument */ context.replacer_function_p = obj_p; } /* 4.b */ - else if (ecma_object_get_class_name (obj_p) == LIT_MAGIC_STRING_ARRAY_UL) + else if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_ARRAY) { ecma_extended_object_t *array_object_p = (ecma_extended_object_t *) obj_p; uint32_t array_length = array_object_p->u.array.length; @@ -1382,9 +1380,7 @@ ecma_builtin_json_stringify (ecma_value_t this_arg, /**< 'this' argument */ /* 4.b.iii.5 */ while (index < array_length) { - ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (index); - ecma_value_t value = ecma_op_object_get (obj_p, index_str_p); - ecma_deref_ecma_string (index_str_p); + ecma_value_t value = ecma_op_object_get_by_uint32_index (obj_p, index); if (ECMA_IS_VALUE_ERROR (value)) { @@ -1409,20 +1405,24 @@ ecma_builtin_json_stringify (ecma_value_t this_arg, /**< 'this' argument */ item = ecma_make_string_value (number_str_p); } /* 4.b.iii.5.f */ - else if (ecma_is_value_object (value) - && (ecma_object_get_class_name (ecma_get_object_from_value (value)) == LIT_MAGIC_STRING_NUMBER_UL - || ecma_object_get_class_name (ecma_get_object_from_value (value)) == LIT_MAGIC_STRING_STRING_UL)) + else if (ecma_is_value_object (value)) { - ecma_string_t *str_p = ecma_op_to_string (value); + ecma_object_t *value_obj_p = ecma_get_object_from_value (value); + lit_magic_string_id_t class_id = ecma_object_get_class_name (value_obj_p); - if (JERRY_UNLIKELY (str_p == NULL)) + if (class_id == LIT_MAGIC_STRING_NUMBER_UL || class_id == LIT_MAGIC_STRING_STRING_UL) { - ecma_collection_free (context.property_list_p); - ecma_free_value (value); - return ECMA_VALUE_ERROR; - } + ecma_string_t *str_p = ecma_op_to_string (value); - item = ecma_make_string_value (str_p); + if (JERRY_UNLIKELY (str_p == NULL)) + { + ecma_collection_free (context.property_list_p); + ecma_free_value (value); + return ECMA_VALUE_ERROR; + } + + item = ecma_make_string_value (str_p); + } } ecma_free_value (value); diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-promise.c b/jerry-core/ecma/builtin-objects/ecma-builtin-promise.c index 5d0bf04a5..05787b834 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-promise.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-promise.c @@ -228,9 +228,7 @@ ecma_builtin_promise_do_race (ecma_value_t array, /**< the array for race */ } /* e. */ - ecma_string_t *index_to_str_p = ecma_new_ecma_string_from_uint32 (index); - ecma_value_t array_item = ecma_op_object_get (array_p, index_to_str_p); - ecma_deref_ecma_string (index_to_str_p); + ecma_value_t array_item = ecma_op_object_get_by_uint32_index (array_p, index); /* f. */ if (ECMA_IS_VALUE_ERROR (array_item)) @@ -359,13 +357,11 @@ ecma_builtin_promise_all_handler (const ecma_value_t function, /**< the function JERRY_ASSERT (ecma_is_value_integer_number (index_val)); /* 8. */ - ecma_string_t *index_to_str_p = ecma_new_ecma_string_from_uint32 ((uint32_t) ecma_get_integer_from_value (index_val)); + ecma_op_object_put_by_uint32_index (ecma_get_object_from_value (value_array), + (uint32_t) ecma_get_integer_from_value (index_val), + argv[0], + false); - ecma_op_object_put (ecma_get_object_from_value (value_array), - index_to_str_p, - argv[0], - false); - ecma_deref_ecma_string (index_to_str_p); /* 9-10. */ if (ecma_builtin_promise_remaining_inc_or_dec (remaining, false) == 0) 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 94b49a7ec..49851ed68 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.c @@ -26,7 +26,6 @@ #include "ecma-iterator-object.h" #include "ecma-objects.h" #include "ecma-string-object.h" -#include "ecma-try-catch-macro.h" #include "jcontext.h" #include "jrt.h" #include "jrt-libc-includes.h" @@ -284,28 +283,24 @@ static ecma_value_t ecma_builtin_string_prepare_search (ecma_value_t regexp_arg, /**< regex argument */ ecma_value_t *regexp_value) /**< [out] ptr to store the regexp object */ { - ecma_value_t ret_value = ECMA_VALUE_EMPTY; - /* 3. */ if (ecma_is_value_object (regexp_arg) && ecma_object_class_is (ecma_get_object_from_value (regexp_arg), LIT_MAGIC_STRING_REGEXP_UL)) { *regexp_value = ecma_copy_value (regexp_arg); + return ECMA_VALUE_EMPTY; } - else + + /* 4. */ + ecma_value_t regexp_arguments[1] = { regexp_arg }; + ecma_value_t new_regexp_value = ecma_builtin_regexp_dispatch_construct (regexp_arguments, 1); + + if (!ECMA_IS_VALUE_ERROR (new_regexp_value)) { - /* 4. */ - ecma_value_t regexp_arguments[1] = { regexp_arg }; - ECMA_TRY_CATCH (new_regexp_value, - ecma_builtin_regexp_dispatch_construct (regexp_arguments, 1), - ret_value); - - *regexp_value = ecma_copy_value (new_regexp_value); - - ECMA_FINALIZE (new_regexp_value); + *regexp_value = new_regexp_value; } - return ret_value; + return new_regexp_value; } /* ecma_builtin_string_prepare_search */ /** @@ -390,8 +385,10 @@ ecma_builtin_string_prototype_object_match (ecma_value_t this_to_string_value, / /* 8.e. */ bool last_match = true; + ret_value = ECMA_VALUE_ERROR; + /* 8.f. */ - while (last_match && ecma_is_value_empty (ret_value)) + while (last_match) { /* 8.f.i. */ ecma_value_t exec_value = ecma_regexp_exec_helper (regexp_value, this_to_string_value, false); @@ -408,13 +405,20 @@ ecma_builtin_string_prototype_object_match (ecma_value_t this_to_string_value, / } /* 8.f.iii. */ - ECMA_TRY_CATCH (this_index_value, - ecma_op_object_get_by_magic_id (regexp_obj_p, LIT_MAGIC_STRING_LASTINDEX_UL), - ret_value); + ecma_value_t this_index_value = ecma_op_object_get_by_magic_id (regexp_obj_p, LIT_MAGIC_STRING_LASTINDEX_UL); - ECMA_TRY_CATCH (this_index_number, - ecma_op_to_number (this_index_value), - ret_value); + if (ECMA_IS_VALUE_ERROR (this_index_value)) + { + goto cleanup; + } + + ecma_value_t this_index_number = ecma_op_to_number (this_index_value); + + if (ECMA_IS_VALUE_ERROR (this_index_value)) + { + ecma_free_value (this_index_value); + goto cleanup; + } ecma_number_t this_index = ecma_get_number_from_value (this_index_number); @@ -422,17 +426,19 @@ ecma_builtin_string_prototype_object_match (ecma_value_t this_to_string_value, / if (this_index == previous_last_index) { /* 8.f.iii.2.a. */ - ECMA_TRY_CATCH (index_put_value, - ecma_op_object_put (regexp_obj_p, - ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), - ecma_make_number_value (this_index + 1), - true), - ret_value); + ecma_value_t index_put_value = ecma_op_object_put (regexp_obj_p, + ecma_get_magic_string (LIT_MAGIC_STRING_LASTINDEX_UL), + ecma_make_number_value (this_index + 1), + true); + if (ECMA_IS_VALUE_ERROR (index_put_value)) + { + ecma_free_value (this_index_value); + ecma_free_number (this_index_number); + goto cleanup; + } /* 8.f.iii.2.b. */ previous_last_index = this_index + 1; - - ECMA_FINALIZE (index_put_value); } else { @@ -440,55 +446,44 @@ ecma_builtin_string_prototype_object_match (ecma_value_t this_to_string_value, / previous_last_index = this_index; } - if (ecma_is_value_empty (ret_value)) - { - /* 8.f.iii.4. */ - JERRY_ASSERT (ecma_is_value_object (exec_value)); - ecma_object_t *exec_obj_p = ecma_get_object_from_value (exec_value); + /* 8.f.iii.4. */ + JERRY_ASSERT (ecma_is_value_object (exec_value)); + ecma_object_t *exec_obj_p = ecma_get_object_from_value (exec_value); - ECMA_TRY_CATCH (match_string_value, - ecma_op_object_get (exec_obj_p, index_zero_string_p), - ret_value); + ecma_value_t match_string_value = ecma_op_object_get (exec_obj_p, index_zero_string_p); + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (match_string_value)); - ecma_string_t *current_index_str_p = ecma_new_ecma_string_from_uint32 (n); + /* 8.f.iii.5. */ + ecma_value_t completion; + completion = ecma_builtin_helper_def_prop_by_index (new_array_obj_p, + n, + match_string_value, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); - /* 8.f.iii.5. */ - ecma_value_t completion = ecma_builtin_helper_def_prop (new_array_obj_p, - current_index_str_p, - match_string_value, - ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + JERRY_ASSERT (ecma_is_value_true (completion)); + /* 8.f.iii.6. */ + n++; - JERRY_ASSERT (ecma_is_value_true (completion)); + ecma_free_value (match_string_value); + ecma_free_value (this_index_value); + ecma_free_number (this_index_number); - ecma_deref_ecma_string (current_index_str_p); - - /* 8.f.iii.6. */ - n++; - - ECMA_FINALIZE (match_string_value); - } - - ECMA_FINALIZE (this_index_number); - - ECMA_FINALIZE (this_index_value); - - ecma_free_value (exec_value); + ecma_deref_object (exec_obj_p); } - if (ecma_is_value_empty (ret_value)) + if (n == 0) { - if (n == 0) - { - /* 8.g. */ - ret_value = ECMA_VALUE_NULL; - } - else - { - /* 8.h. */ - ret_value = ecma_copy_value (new_array_value); - } + /* 8.g. */ + ret_value = ECMA_VALUE_NULL; + } + else + { + /* 8.h. */ + ecma_ref_object (new_array_obj_p); + ret_value = new_array_value; } +cleanup: ecma_deref_object (new_array_obj_p); ecma_deref_object (regexp_obj_p); @@ -590,7 +585,7 @@ ecma_builtin_string_prototype_object_replace_match (ecma_builtin_replace_search_ } JERRY_ASSERT (ecma_is_value_number (index_value)); - ecma_value_t result_string_value = ecma_op_object_get (match_object_p, ecma_get_ecma_string_from_uint32 (0)); + ecma_value_t result_string_value = ecma_op_object_get_by_uint32_index (match_object_p, 0); if (ECMA_IS_VALUE_ERROR (result_string_value)) { @@ -650,29 +645,16 @@ ecma_builtin_string_prototype_object_replace_get_string (ecma_builtin_replace_se * context */ ecma_value_t match_value) /**< returned match value */ { - ecma_value_t ret_value = ECMA_VALUE_EMPTY; ecma_object_t *match_object_p = ecma_get_object_from_value (match_value); + JERRY_ASSERT (ecma_get_object_type (match_object_p) == ECMA_OBJECT_TYPE_ARRAY); - ecma_value_t match_length_value = ecma_op_object_get_by_magic_id (match_object_p, LIT_MAGIC_STRING_LENGTH); + ecma_length_t match_length = ecma_array_get_length (match_object_p); - if (ECMA_IS_VALUE_ERROR (match_length_value)) - { - return match_length_value; - } - - JERRY_ASSERT (ecma_is_value_number (match_length_value)); - - ecma_number_t match_length_number = ecma_get_number_from_value (match_length_value); - ecma_length_t match_length = (ecma_length_t) (match_length_number); - ecma_free_number (match_length_value); - - JERRY_ASSERT ((ecma_length_t) ecma_number_to_uint32 (match_length_number) == match_length); JERRY_ASSERT (match_length >= 1); if (context_p->is_replace_callable) { - ret_value = ECMA_VALUE_ERROR; - + ecma_value_t ret_value = ECMA_VALUE_ERROR; JMEM_DEFINE_LOCAL_ARRAY (arguments_list, match_length + 2, ecma_value_t); @@ -681,11 +663,9 @@ ecma_builtin_string_prototype_object_replace_get_string (ecma_builtin_replace_se * uninitalized elements must not be freed. */ ecma_length_t values_copied = 0; - for (ecma_length_t i = 0; i < match_length; i++) + for (ecma_length_t i = 0; i < match_length ;i++) { - ecma_string_t *index_p = ecma_new_ecma_string_from_uint32 (i); - ecma_value_t current_value = ecma_op_object_get (match_object_p, index_p); - ecma_deref_ecma_string (index_p); + ecma_value_t current_value = ecma_op_object_get_by_uint32_index (match_object_p, i); if (ECMA_IS_VALUE_ERROR (current_value)) { @@ -715,7 +695,7 @@ ecma_builtin_string_prototype_object_replace_get_string (ecma_builtin_replace_se ecma_string_t *to_string_p = ecma_op_to_string (result_value); ecma_free_value (result_value); - if (JERRY_UNLIKELY (to_string_p != NULL)) + if (JERRY_LIKELY (to_string_p != NULL)) { ret_value = ecma_make_string_value (to_string_p); } @@ -727,203 +707,192 @@ cleanup: } JMEM_FINALIZE_LOCAL_ARRAY (arguments_list); + + return ret_value; } - else + + /* Although the ECMA standard does not specify how $nn (n is a decimal + * number) captures should be replaced if nn is greater than the maximum + * capture index, we follow the test-262 expected behaviour: + * + * if maximum capture index is < 10 + * we replace only those $n and $0n captures, where n < maximum capture index + * otherwise + * we replace only those $nn captures, where nn < maximum capture index + * + * other $n $nn sequences left unchanged + * + * example: "".replace(/(x)y/, "$1,$2,$01,$12") === "" + */ + + ecma_string_t *result_string_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); + + ecma_length_t previous_start = 0; + ecma_length_t current_position = 0; + + lit_utf8_byte_t *replace_str_curr_p = context_p->replace_str_curr_p; + lit_utf8_byte_t *replace_str_end_p = replace_str_curr_p + ecma_string_get_size (context_p->replace_string_p); + + while (replace_str_curr_p < replace_str_end_p) { - /* Although the ECMA standard does not specify how $nn (n is a decimal - * number) captures should be replaced if nn is greater than the maximum - * capture index, we follow the test-262 expected behaviour: - * - * if maximum capture index is < 10 - * we replace only those $n and $0n captures, where n < maximum capture index - * otherwise - * we replace only those $nn captures, where nn < maximum capture index - * - * other $n $nn sequences left unchanged - * - * example: "".replace(/(x)y/, "$1,$2,$01,$12") === "" - */ + ecma_char_t action = LIT_CHAR_NULL; - ecma_string_t *result_string_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); - - ecma_length_t previous_start = 0; - ecma_length_t current_position = 0; - - lit_utf8_byte_t *replace_str_curr_p = context_p->replace_str_curr_p; - lit_utf8_byte_t *replace_str_end_p = replace_str_curr_p + ecma_string_get_size (context_p->replace_string_p); - - while (replace_str_curr_p < replace_str_end_p) + if (*replace_str_curr_p != LIT_CHAR_DOLLAR_SIGN) { - ecma_char_t action = LIT_CHAR_NULL; - - if (*replace_str_curr_p != LIT_CHAR_DOLLAR_SIGN) + /* if not a continuation byte */ + if ((*replace_str_curr_p & LIT_UTF8_EXTRA_BYTE_MASK) != LIT_UTF8_EXTRA_BYTE_MARKER) { - /* if not a continuation byte */ - if ((*replace_str_curr_p & LIT_UTF8_EXTRA_BYTE_MASK) != LIT_UTF8_EXTRA_BYTE_MARKER) - { - current_position++; - } - replace_str_curr_p++; - continue; + current_position++; } - replace_str_curr_p++; + continue; + } - if (replace_str_curr_p < replace_str_end_p) + replace_str_curr_p++; + + if (replace_str_curr_p < replace_str_end_p) + { + action = *replace_str_curr_p; + + if (action == LIT_CHAR_DOLLAR_SIGN) { - action = *replace_str_curr_p; + current_position++; + } + else if (action >= LIT_CHAR_0 && action <= LIT_CHAR_9) + { + uint32_t index = 0; - if (action == LIT_CHAR_DOLLAR_SIGN) - { - current_position++; - } - else if (action >= LIT_CHAR_0 && action <= LIT_CHAR_9) - { - uint32_t index = 0; + index = (uint32_t) (action - LIT_CHAR_0); - index = (uint32_t) (action - LIT_CHAR_0); - - if (index >= match_length) - { - action = LIT_CHAR_NULL; - } - else if (index == 0 || match_length > 10) - { - replace_str_curr_p++; - - if (replace_str_curr_p < replace_str_end_p) - { - ecma_char_t next_character = *replace_str_curr_p; - - if (next_character >= LIT_CHAR_0 && next_character <= LIT_CHAR_9) - { - uint32_t full_index = index * 10 + (uint32_t) (next_character - LIT_CHAR_0); - if (full_index > 0 && full_index < match_length) - { - index = match_length; - } - } - } - - replace_str_curr_p--; - - if (index == 0) - { - action = LIT_CHAR_NULL; - } - } - } - else if (action != LIT_CHAR_AMPERSAND - && action != LIT_CHAR_GRAVE_ACCENT - && action != LIT_CHAR_SINGLE_QUOTE) + if (index >= match_length) { action = LIT_CHAR_NULL; } - } - - if (action != LIT_CHAR_NULL) - { - result_string_p = ecma_builtin_string_prototype_object_replace_append_substr (result_string_p, - context_p->replace_string_p, - previous_start, - current_position); - replace_str_curr_p++; - current_position++; - - if (action == LIT_CHAR_DOLLAR_SIGN) + else if (index == 0 || match_length > 10) { - current_position--; - } - else if (action == LIT_CHAR_GRAVE_ACCENT) - { - ecma_string_t *input_string_p = ecma_get_string_from_value (context_p->input_string); - result_string_p = ecma_builtin_string_prototype_object_replace_append_substr (result_string_p, - input_string_p, - 0, - context_p->match_start); - } - else if (action == LIT_CHAR_SINGLE_QUOTE) - { - ecma_string_t *input_string_p = ecma_get_string_from_value (context_p->input_string); - result_string_p = ecma_builtin_string_prototype_object_replace_append_substr (result_string_p, - input_string_p, - context_p->match_end, - context_p->input_length); - } - else - { - /* Everything else is submatch reading. */ - uint32_t index = 0; + replace_str_curr_p++; - JERRY_ASSERT (action == LIT_CHAR_AMPERSAND || (action >= LIT_CHAR_0 && action <= LIT_CHAR_9)); - - if (action >= LIT_CHAR_0 && action <= LIT_CHAR_9) + if (replace_str_curr_p < replace_str_end_p) { - index = (uint32_t) (action - LIT_CHAR_0); + ecma_char_t next_character = *replace_str_curr_p; - if ((match_length > 10 || index == 0) - && replace_str_curr_p < replace_str_end_p) + if (next_character >= LIT_CHAR_0 && next_character <= LIT_CHAR_9) { - action = *replace_str_curr_p; - if (action >= LIT_CHAR_0 && action <= LIT_CHAR_9) + uint32_t full_index = index * 10 + (uint32_t) (next_character - LIT_CHAR_0); + if (full_index > 0 && full_index < match_length) { - uint32_t full_index = index * 10 + (uint32_t) (action - LIT_CHAR_0); - if (full_index < match_length) - { - index = full_index; - replace_str_curr_p++; - current_position++; - } + index = match_length; } } - JERRY_ASSERT (index > 0 && index < match_length); } - ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index); + replace_str_curr_p--; - ECMA_TRY_CATCH (submatch_value, - ecma_op_object_get (match_object_p, index_string_p), - ret_value); - - /* Undefined values are converted to empty string. */ - if (!ecma_is_value_undefined (submatch_value)) + if (index == 0) { - JERRY_ASSERT (ecma_is_value_string (submatch_value)); - ecma_string_t *submatch_string_p = ecma_get_string_from_value (submatch_value); - - result_string_p = ecma_concat_ecma_strings (result_string_p, submatch_string_p); - } - - ECMA_FINALIZE (submatch_value); - ecma_deref_ecma_string (index_string_p); - - if (!ecma_is_value_empty (ret_value)) - { - break; + action = LIT_CHAR_NULL; } } - - current_position++; - previous_start = current_position; } - else + else if (action != LIT_CHAR_AMPERSAND + && action != LIT_CHAR_GRAVE_ACCENT + && action != LIT_CHAR_SINGLE_QUOTE) { - current_position++; + action = LIT_CHAR_NULL; } } - if (ecma_is_value_empty (ret_value)) + if (action != LIT_CHAR_NULL) { result_string_p = ecma_builtin_string_prototype_object_replace_append_substr (result_string_p, context_p->replace_string_p, previous_start, current_position); + replace_str_curr_p++; + current_position++; - ret_value = ecma_make_string_value (result_string_p); + if (action == LIT_CHAR_DOLLAR_SIGN) + { + current_position--; + } + else if (action == LIT_CHAR_GRAVE_ACCENT) + { + ecma_string_t *input_string_p = ecma_get_string_from_value (context_p->input_string); + result_string_p = ecma_builtin_string_prototype_object_replace_append_substr (result_string_p, + input_string_p, + 0, + context_p->match_start); + } + else if (action == LIT_CHAR_SINGLE_QUOTE) + { + ecma_string_t *input_string_p = ecma_get_string_from_value (context_p->input_string); + result_string_p = ecma_builtin_string_prototype_object_replace_append_substr (result_string_p, + input_string_p, + context_p->match_end, + context_p->input_length); + } + else + { + /* Everything else is submatch reading. */ + uint32_t index = 0; + + JERRY_ASSERT (action == LIT_CHAR_AMPERSAND || (action >= LIT_CHAR_0 && action <= LIT_CHAR_9)); + + if (action >= LIT_CHAR_0 && action <= LIT_CHAR_9) + { + index = (uint32_t) (action - LIT_CHAR_0); + + if ((match_length > 10 || index == 0) + && replace_str_curr_p < replace_str_end_p) + { + action = *replace_str_curr_p; + if (action >= LIT_CHAR_0 && action <= LIT_CHAR_9) + { + uint32_t full_index = index * 10 + (uint32_t) (action - LIT_CHAR_0); + if (full_index < match_length) + { + index = full_index; + replace_str_curr_p++; + current_position++; + } + } + } + JERRY_ASSERT (index > 0 && index < match_length); + } + + ecma_value_t submatch_value = ecma_op_object_get_by_uint32_index (match_object_p, index); + + if (ECMA_IS_VALUE_ERROR (submatch_value)) + { + return submatch_value; + } + + /* Undefined values are converted to empty string. */ + if (!ecma_is_value_undefined (submatch_value)) + { + JERRY_ASSERT (ecma_is_value_string (submatch_value)); + ecma_string_t *submatch_string_p = ecma_get_string_from_value (submatch_value); + + result_string_p = ecma_concat_ecma_strings (result_string_p, submatch_string_p); + ecma_free_value (submatch_value); + } + } + + current_position++; + previous_start = current_position; + } + else + { + current_position++; } } - return ret_value; + result_string_p = ecma_builtin_string_prototype_object_replace_append_substr (result_string_p, + context_p->replace_string_p, + previous_start, + current_position); + + return ecma_make_string_value (result_string_p); } /* ecma_builtin_string_prototype_object_replace_get_string */ /** @@ -1078,7 +1047,6 @@ ecma_builtin_string_prototype_object_replace_main (ecma_builtin_replace_search_c * The String.prototype object's 'replace' routine * * The replace algorithm is splitted into several helper functions. - * This allows using ECMA_TRY_CATCH macros and avoiding early returns. * * To share data between these helper functions, we created a * structure called ecma_builtin_replace_search_ctx_t, which @@ -1189,11 +1157,9 @@ ecma_builtin_string_prototype_object_search (ecma_value_t to_string_value, /**< ecma_value_t regexp_value = ECMA_VALUE_EMPTY; - ecma_value_t ret_value = ecma_builtin_string_prepare_search (regexp_arg, ®exp_value); - - if (ECMA_IS_VALUE_ERROR (ret_value)) + if (ECMA_IS_VALUE_ERROR (ecma_builtin_string_prepare_search (regexp_arg, ®exp_value))) { - return ret_value; + return ECMA_VALUE_ERROR; } /* 5. */ @@ -1202,11 +1168,11 @@ ecma_builtin_string_prototype_object_search (ecma_value_t to_string_value, /**< ecma_value_t match_result = ecma_regexp_exec_helper (regexp_value, to_string_value, true); + ecma_value_t ret_value = ECMA_VALUE_ERROR; + if (ECMA_IS_VALUE_ERROR (match_result)) { - ecma_free_value (regexp_value); - ecma_deref_ecma_string (this_string_p); - return match_result; + goto cleanup; } ecma_number_t offset = -1; @@ -1217,23 +1183,20 @@ ecma_builtin_string_prototype_object_search (ecma_value_t to_string_value, /**< ecma_object_t *match_object_p = ecma_get_object_from_value (match_result); - ECMA_TRY_CATCH (index_value, - ecma_op_object_get_by_magic_id (match_object_p, LIT_MAGIC_STRING_INDEX), - ret_value); + ecma_value_t index_value = ecma_op_object_get_by_magic_id (match_object_p, LIT_MAGIC_STRING_INDEX); - JERRY_ASSERT (ecma_is_value_number (index_value)); + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (index_value) && ecma_is_value_number (index_value)); offset = ecma_get_number_from_value (index_value); - ECMA_FINALIZE (index_value); + ecma_free_number (index_value); + ecma_free_value (match_result); } - if (ecma_is_value_empty (ret_value)) - { - ret_value = ecma_make_number_value (offset); - } + ret_value = ecma_make_number_value (offset); - ecma_free_value (match_result); + +cleanup: ecma_free_value (regexp_value); ecma_deref_ecma_string (this_string_p); @@ -1338,24 +1301,18 @@ ecma_builtin_string_prototype_object_split (ecma_value_t this_to_string_val, /** return new_array; } - ecma_value_t ret_value = ECMA_VALUE_EMPTY; - ecma_object_t *new_array_p = ecma_get_object_from_value (new_array); /* 10. */ if (ecma_is_value_undefined (arg1)) { - ecma_string_t *zero_str_p = ecma_new_ecma_string_from_number (ECMA_NUMBER_ZERO); - - ecma_value_t put_comp = ecma_builtin_helper_def_prop (new_array_p, - zero_str_p, - this_to_string_val, - ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + ecma_value_t put_comp = ecma_builtin_helper_def_prop_by_index (new_array_p, + 0, + this_to_string_val, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); JERRY_ASSERT (ecma_is_value_true (put_comp)); - ecma_deref_ecma_string (zero_str_p); - return new_array; } @@ -1386,7 +1343,7 @@ ecma_builtin_string_prototype_object_split (ecma_value_t this_to_string_val, /** const ecma_string_t *this_to_string_p = ecma_get_string_from_value (this_to_string_val); /* 11. */ - if (ecma_string_is_empty (this_to_string_p) && ecma_is_value_empty (ret_value)) + if (ecma_string_is_empty (this_to_string_p)) { bool should_return = false; @@ -1423,15 +1380,12 @@ ecma_builtin_string_prototype_object_split (ecma_value_t this_to_string_val, /** if (!should_return) { /* 11.c */ - ecma_string_t *zero_str_p = ecma_new_ecma_string_from_number (ECMA_NUMBER_ZERO); - - ecma_value_t put_comp = ecma_builtin_helper_def_prop (new_array_p, - zero_str_p, - this_to_string_val, - ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + ecma_value_t put_comp = ecma_builtin_helper_def_prop_by_index (new_array_p, + 0, + this_to_string_val, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); JERRY_ASSERT (ecma_is_value_true (put_comp)); - ecma_deref_ecma_string (zero_str_p); } } else @@ -1451,7 +1405,7 @@ ecma_builtin_string_prototype_object_split (ecma_value_t this_to_string_val, /** /* 6. */ const ecma_length_t string_length = ecma_string_get_length (this_to_string_p); - while (curr_pos < string_length && !should_return && ecma_is_value_empty (ret_value)) + while (curr_pos < string_length && !should_return) { ecma_value_t match_result = ECMA_VALUE_NULL; @@ -1562,12 +1516,11 @@ ecma_builtin_string_prototype_object_split (ecma_value_t this_to_string_val, /** start_pos, end_pos); - ecma_string_t *array_length_str_p = ecma_new_ecma_string_from_uint32 (new_array_length); - - ecma_value_t put_comp = ecma_builtin_helper_def_prop (new_array_p, - array_length_str_p, - ecma_make_string_value (substr_str_p), - ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + ecma_value_t put_comp; + put_comp = ecma_builtin_helper_def_prop_by_index (new_array_p, + new_array_length, + ecma_make_string_value (substr_str_p), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); JERRY_ASSERT (ecma_is_value_true (put_comp)); @@ -1575,7 +1528,7 @@ ecma_builtin_string_prototype_object_split (ecma_value_t this_to_string_val, /** new_array_length++; /* 13.c.iii.4 */ - if (new_array_length == limit && ecma_is_value_empty (ret_value)) + if (new_array_length == limit) { should_return = true; } @@ -1583,35 +1536,25 @@ ecma_builtin_string_prototype_object_split (ecma_value_t this_to_string_val, /** /* 13.c.iii.5 */ start_pos = end_pos + match_str_length; - ECMA_TRY_CATCH (array_length_val, - ecma_op_object_get_by_magic_id (match_obj_p, LIT_MAGIC_STRING_LENGTH), - ret_value); - - ECMA_OP_TO_NUMBER_TRY_CATCH (array_length_num, array_length_val, ret_value); - - /* The first item is the match object, thus we should skip it. */ - const uint32_t match_result_array_length = ecma_number_to_uint32 (array_length_num) - 1; + const uint32_t match_result_array_length = ecma_array_get_length (match_obj_p) - 1; /* 13.c.iii.6 */ uint32_t i = 0; /* 13.c.iii.7 */ - while (i < match_result_array_length && ecma_is_value_empty (ret_value)) + while (i < match_result_array_length) { /* 13.c.iii.7.a */ i++; - ecma_string_t *idx_str_p = ecma_new_ecma_string_from_uint32 (i); - ecma_string_t *new_array_idx_str_p = ecma_new_ecma_string_from_uint32 (new_array_length); - - match_comp_value = ecma_op_object_get (match_obj_p, idx_str_p); + match_comp_value = ecma_op_object_get_by_uint32_index (match_obj_p, i); JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (match_comp_value)); /* 13.c.iii.7.b */ - put_comp = ecma_builtin_helper_def_prop (new_array_p, - new_array_idx_str_p, - match_comp_value, - ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + put_comp = ecma_builtin_helper_def_prop_by_index (new_array_p, + new_array_length, + match_comp_value, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); JERRY_ASSERT (ecma_is_value_true (put_comp)); @@ -1619,22 +1562,17 @@ ecma_builtin_string_prototype_object_split (ecma_value_t this_to_string_val, /** new_array_length++; /* 13.c.iii.7.d */ - if (new_array_length == limit && ecma_is_value_empty (ret_value)) + if (new_array_length == limit) { should_return = true; } ecma_free_value (match_comp_value); - ecma_deref_ecma_string (new_array_idx_str_p); - ecma_deref_ecma_string (idx_str_p); } /* 13.c.iii.8 */ curr_pos = start_pos; - ECMA_OP_TO_NUMBER_FINALIZE (array_length_num); - ECMA_FINALIZE (array_length_val); - ecma_deref_ecma_string (array_length_str_p); ecma_deref_ecma_string (substr_str_p); } @@ -1642,7 +1580,7 @@ ecma_builtin_string_prototype_object_split (ecma_value_t this_to_string_val, /** } - if (!should_return && !separator_is_empty && ecma_is_value_empty (ret_value)) + if (!should_return && !separator_is_empty) { /* 14. */ ecma_string_t *substr_str_p; @@ -1651,32 +1589,20 @@ ecma_builtin_string_prototype_object_split (ecma_value_t this_to_string_val, /** string_length); /* 15. */ - ecma_string_t *array_length_string_p = ecma_new_ecma_string_from_uint32 (new_array_length); - - ecma_value_t put_comp = ecma_builtin_helper_def_prop (new_array_p, - array_length_string_p, - ecma_make_string_value (substr_str_p), - ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); + ecma_value_t put_comp; + put_comp = ecma_builtin_helper_def_prop_by_index (new_array_p, + new_array_length, + ecma_make_string_value (substr_str_p), + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); JERRY_ASSERT (ecma_is_value_true (put_comp)); - - ecma_deref_ecma_string (array_length_string_p); ecma_deref_ecma_string (substr_str_p); } } ecma_free_value (separator); - if (ecma_is_value_empty (ret_value)) - { - ret_value = new_array; - } - else - { - ecma_deref_object (new_array_p); - } - - return ret_value; + return new_array; } /* ecma_builtin_string_prototype_object_split */ /** 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 b49f4cbeb..df9b08801 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 @@ -225,47 +225,47 @@ ecma_builtin_typedarray_prototype_exec_routine (ecma_value_t this_arg, /**< this ecma_number_t element_num = typedarray_getter_cb (info.buffer_p + byte_pos); ecma_value_t get_value = ecma_make_number_value (element_num); - JERRY_ASSERT (ecma_is_value_number (get_value)); - ecma_value_t call_args[] = { get_value, current_index, this_arg }; - ECMA_TRY_CATCH (call_value, ecma_op_function_call (func_object_p, cb_this_arg, call_args, 3), ret_value); + ecma_value_t call_value = ecma_op_function_call (func_object_p, cb_this_arg, call_args, 3); + + ecma_fast_free_value (current_index); + ecma_fast_free_value (get_value); + + if (ECMA_IS_VALUE_ERROR (call_value)) + { + return call_value; + } if (mode == TYPEDARRAY_ROUTINE_EVERY) { if (!ecma_op_to_boolean (call_value)) { - ret_value = ECMA_VALUE_FALSE; + return ECMA_VALUE_FALSE; } } else if (mode == TYPEDARRAY_ROUTINE_SOME && ecma_op_to_boolean (call_value)) { - ret_value = ECMA_VALUE_TRUE; + return ECMA_VALUE_TRUE; } byte_pos += info.element_size; - ECMA_FINALIZE (call_value); - - ecma_fast_free_value (current_index); - ecma_fast_free_value (get_value); + ecma_free_value (call_value); } - if (ecma_is_value_empty (ret_value)) + if (mode == TYPEDARRAY_ROUTINE_EVERY) { - if (mode == TYPEDARRAY_ROUTINE_EVERY) - { - ret_value = ECMA_VALUE_TRUE; - } - else if (mode == TYPEDARRAY_ROUTINE_SOME) - { - ret_value = ECMA_VALUE_FALSE; - } - else - { - ret_value = ECMA_VALUE_UNDEFINED; - } + ret_value = ECMA_VALUE_TRUE; + } + else if (mode == TYPEDARRAY_ROUTINE_SOME) + { + ret_value = ECMA_VALUE_FALSE; + } + else + { + ret_value = ECMA_VALUE_UNDEFINED; } return ret_value; @@ -709,7 +709,7 @@ ecma_builtin_typedarray_prototype_filter (ecma_value_t this_arg, /**< this argum ecma_typedarray_getter_fn_t getter_cb = ecma_get_typedarray_getter_fn (info.id); ecma_object_t *func_object_p = ecma_get_object_from_value (cb_func_val); - ecma_value_t ret_value = ECMA_VALUE_EMPTY; + ecma_value_t ret_value = ECMA_VALUE_ERROR; if (info.length == 0) { @@ -721,7 +721,7 @@ ecma_builtin_typedarray_prototype_filter (ecma_value_t this_arg, /**< this argum lit_utf8_byte_t *pass_value_p = pass_value_list_p; ecma_length_t byte_pos = 0; - for (uint32_t index = 0; index < info.length && ecma_is_value_empty (ret_value); index++) + for (uint32_t index = 0; index < info.length; index++) { ecma_value_t current_index = ecma_make_uint32_value (index); ecma_number_t get_num = getter_cb (info.buffer_p + byte_pos); @@ -731,7 +731,15 @@ ecma_builtin_typedarray_prototype_filter (ecma_value_t this_arg, /**< this argum ecma_value_t call_args[] = { get_value, current_index, this_arg }; - ECMA_TRY_CATCH (call_value, ecma_op_function_call (func_object_p, cb_this_arg, call_args, 3), ret_value); + ecma_fast_free_value (current_index); + ecma_fast_free_value (get_value); + + ecma_value_t call_value = ecma_op_function_call (func_object_p, cb_this_arg, call_args, 3); + + if (ECMA_IS_VALUE_ERROR (call_value)) + { + goto cleanup; + } if (ecma_op_to_boolean (call_value)) { @@ -741,30 +749,25 @@ ecma_builtin_typedarray_prototype_filter (ecma_value_t this_arg, /**< this argum byte_pos += info.element_size; - ECMA_FINALIZE (call_value); - - ecma_fast_free_value (current_index); - ecma_fast_free_value (get_value); + ecma_free_value (call_value); } - if (ecma_is_value_empty (ret_value)) + uint32_t pass_num = (uint32_t) ((pass_value_p - pass_value_list_p) >> info.shift); + + ret_value = ecma_op_create_typedarray_with_type_and_length (obj_p, pass_num); + + if (!ECMA_IS_VALUE_ERROR (ret_value)) { - uint32_t pass_num = (uint32_t) ((pass_value_p - pass_value_list_p) >> info.shift); + obj_p = ecma_get_object_from_value (ret_value); - ret_value = ecma_op_create_typedarray_with_type_and_length (obj_p, pass_num); + JERRY_ASSERT (ecma_typedarray_get_offset (obj_p) == 0); - if (!ECMA_IS_VALUE_ERROR (ret_value)) - { - obj_p = ecma_get_object_from_value (ret_value); - - JERRY_ASSERT (ecma_typedarray_get_offset (obj_p) == 0); - - memcpy (ecma_typedarray_get_buffer (obj_p), - pass_value_list_p, - (size_t) (pass_value_p - pass_value_list_p)); - } + memcpy (ecma_typedarray_get_buffer (obj_p), + pass_value_list_p, + (size_t) (pass_value_p - pass_value_list_p)); } +cleanup: JMEM_FINALIZE_LOCAL_ARRAY (pass_value_list_p); return ret_value; @@ -985,10 +988,8 @@ ecma_builtin_typedarray_prototype_set (ecma_value_t this_arg, /**< this argument while (k < source_length_uint32 && ecma_is_value_empty (ret_val)) { - ecma_string_t *k_str_p = ecma_new_ecma_string_from_uint32 (k); - ECMA_TRY_CATCH (elem, - ecma_op_object_get (source_obj_p, k_str_p), + ecma_op_object_get_by_uint32_index (source_obj_p, k), ret_val); ECMA_OP_TO_NUMBER_TRY_CATCH (elem_num, elem, ret_val); @@ -998,8 +999,6 @@ ecma_builtin_typedarray_prototype_set (ecma_value_t this_arg, /**< this argument ECMA_OP_TO_NUMBER_FINALIZE (elem_num); ECMA_FINALIZE (elem); - ecma_deref_ecma_string (k_str_p); - k++; target_byte_index += target_info.element_size; } @@ -1029,9 +1028,7 @@ static ecma_string_t * ecma_op_typedarray_get_to_string_at_index (ecma_object_t *obj_p, /**< this object */ uint32_t index) /**< array index */ { - ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index); - ecma_value_t index_value = ecma_op_object_get (obj_p, index_string_p); - ecma_deref_ecma_string (index_string_p); + ecma_value_t index_value = ecma_op_object_get_by_uint32_index (obj_p, index); if (ECMA_IS_VALUE_ERROR (index_value)) { diff --git a/jerry-core/ecma/operations/ecma-array-object.c b/jerry-core/ecma/operations/ecma-array-object.c index 439fbefe1..6d126f984 100644 --- a/jerry-core/ecma/operations/ecma-array-object.c +++ b/jerry-core/ecma/operations/ecma-array-object.c @@ -1088,6 +1088,19 @@ ecma_op_array_object_define_own_property (ecma_object_t *object_p, /**< the arra return ECMA_VALUE_TRUE; } /* ecma_op_array_object_define_own_property */ +/** + * Get the length of the an array object + * + * @return the array length + */ +extern inline uint32_t JERRY_ATTR_ALWAYS_INLINE +ecma_array_get_length (ecma_object_t *array_p) /**< array object */ +{ + JERRY_ASSERT (ecma_get_object_type (array_p) == ECMA_OBJECT_TYPE_ARRAY); + + return ((ecma_extended_object_t *) array_p)->u.array.length; +} /* ecma_array_get_length */ + /** * List names of a String object's lazy instantiated properties * diff --git a/jerry-core/ecma/operations/ecma-array-object.h b/jerry-core/ecma/operations/ecma-array-object.h index a718d2a27..d105d8974 100644 --- a/jerry-core/ecma/operations/ecma-array-object.h +++ b/jerry-core/ecma/operations/ecma-array-object.h @@ -88,6 +88,8 @@ 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); +uint32_t ecma_array_get_length (ecma_object_t *array_p); + void ecma_op_array_list_lazy_property_names (ecma_object_t *obj_p, bool separate_enumerable, ecma_collection_t *main_collection_p, diff --git a/jerry-core/ecma/operations/ecma-container-object.c b/jerry-core/ecma/operations/ecma-container-object.c index 49b75159b..d42850b3e 100644 --- a/jerry-core/ecma/operations/ecma-container-object.c +++ b/jerry-core/ecma/operations/ecma-container-object.c @@ -129,7 +129,7 @@ ecma_op_container_create (const ecma_value_t *arguments_list_p, /**< arguments l ecma_object_t *next_object_p = ecma_get_object_from_value (next_value); - ecma_value_t key = ecma_op_object_get (next_object_p, ecma_new_ecma_string_from_uint32 (0)); + ecma_value_t key = ecma_op_object_get_by_uint32_index (next_object_p, 0); if (ECMA_IS_VALUE_ERROR (key)) { @@ -141,7 +141,7 @@ ecma_op_container_create (const ecma_value_t *arguments_list_p, /**< arguments l return key; } - ecma_value_t value = ecma_op_object_get (next_object_p, ecma_new_ecma_string_from_uint32 (1)); + ecma_value_t value = ecma_op_object_get_by_uint32_index (next_object_p, 1); if (ECMA_IS_VALUE_ERROR (value)) { diff --git a/jerry-core/ecma/operations/ecma-function-object.c b/jerry-core/ecma/operations/ecma-function-object.c index 6c5152b2f..e2e8871f0 100644 --- a/jerry-core/ecma/operations/ecma-function-object.c +++ b/jerry-core/ecma/operations/ecma-function-object.c @@ -50,6 +50,22 @@ ecma_is_normal_or_arrow_function (ecma_object_type_t type) /**< object type */ #endif /* ENABLED (JERRY_ES2015) */ } /* ecma_is_normal_or_arrow_function */ +/** + * IsCallable operation. + * + * See also: ECMA-262 v5, 9.11 + * + * @return true - if the given object is callable; + * false - otherwise + */ +inline bool JERRY_ATTR_ALWAYS_INLINE +ecma_op_object_is_callable (ecma_object_t *obj_p) /**< ecma object */ +{ + JERRY_ASSERT (!ecma_is_lexical_environment (obj_p)); + + return ecma_get_object_type (obj_p) >= ECMA_OBJECT_TYPE_FUNCTION; +} /* ecma_op_object_is_callable */ + /** * IsCallable operation. * @@ -61,25 +77,30 @@ ecma_is_normal_or_arrow_function (ecma_object_type_t type) /**< object type */ bool ecma_op_is_callable (ecma_value_t value) /**< ecma value */ { - if (!ecma_is_value_object (value)) - { - return false; - } + return (ecma_is_value_object (value) + && ecma_op_object_is_callable (ecma_get_object_from_value (value))); +} /* ecma_op_is_callable */ - ecma_object_t *obj_p = ecma_get_object_from_value (value); - - JERRY_ASSERT (obj_p != NULL); +/** + * Checks whether the given object implements [[Construct]]. + * + * @return true - if the given object is constructor; + * false - otherwise + */ +inline bool JERRY_ATTR_ALWAYS_INLINE +ecma_object_is_constructor (ecma_object_t *obj_p) /**< ecma object */ +{ JERRY_ASSERT (!ecma_is_lexical_environment (obj_p)); ecma_object_type_t type = ecma_get_object_type (obj_p); - return (type == ECMA_OBJECT_TYPE_FUNCTION -#if ENABLED (JERRY_ES2015) - || type == ECMA_OBJECT_TYPE_ARROW_FUNCTION -#endif /* ENABLED (JERRY_ES2015) */ - || type == ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION - || type == ECMA_OBJECT_TYPE_BOUND_FUNCTION); -} /* ecma_op_is_callable */ + if (type == ECMA_OBJECT_TYPE_FUNCTION) + { + return (!ecma_get_object_is_builtin (obj_p) || !ecma_builtin_function_is_routine (obj_p)); + } + + return (type >= ECMA_OBJECT_TYPE_BOUND_FUNCTION); +} /* ecma_object_is_constructor */ /** * Checks whether the value is Object that implements [[Construct]]. @@ -90,24 +111,8 @@ ecma_op_is_callable (ecma_value_t value) /**< ecma value */ bool ecma_is_constructor (ecma_value_t value) /**< ecma value */ { - if (!ecma_is_value_object (value)) - { - return false; - } - - ecma_object_t *obj_p = ecma_get_object_from_value (value); - - JERRY_ASSERT (obj_p != NULL); - JERRY_ASSERT (!ecma_is_lexical_environment (obj_p)); - - if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_FUNCTION) - { - return (!ecma_get_object_is_builtin (obj_p) - || !ecma_builtin_function_is_routine (obj_p)); - } - - return (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_BOUND_FUNCTION - || ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION); + return (ecma_is_value_object (value) + && ecma_object_is_constructor (ecma_get_object_from_value (value))); } /* ecma_is_constructor */ /** diff --git a/jerry-core/ecma/operations/ecma-function-object.h b/jerry-core/ecma/operations/ecma-function-object.h index 435bda111..473c221f0 100644 --- a/jerry-core/ecma/operations/ecma-function-object.h +++ b/jerry-core/ecma/operations/ecma-function-object.h @@ -29,7 +29,9 @@ bool ecma_is_normal_or_arrow_function (ecma_object_type_t type); bool ecma_op_is_callable (ecma_value_t value); +bool ecma_op_object_is_callable (ecma_object_t *obj_p); bool ecma_is_constructor (ecma_value_t value); +bool ecma_object_is_constructor (ecma_object_t *obj_p); ecma_object_t * ecma_op_create_function_object (ecma_object_t *scope_p, const ecma_compiled_code_t *bytecode_data_p); diff --git a/jerry-core/ecma/operations/ecma-objects.c b/jerry-core/ecma/operations/ecma-objects.c index b68fc571b..0288c1553 100644 --- a/jerry-core/ecma/operations/ecma-objects.c +++ b/jerry-core/ecma/operations/ecma-objects.c @@ -171,7 +171,7 @@ ecma_op_object_get_own_property (ecma_object_t *object_p, /**< the object */ case ECMA_OBJECT_TYPE_PSEUDO_ARRAY: { /* ES2015 9.4.5.1 */ - if (ecma_is_typedarray (ecma_make_object_value (object_p))) + if (ecma_object_is_typedarray (object_p)) { #if ENABLED (JERRY_ES2015) if (ecma_prop_name_is_symbol (property_name_p)) @@ -540,7 +540,7 @@ ecma_op_object_find_own (ecma_value_t base_value, /**< base value */ } #if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) /* ES2015 9.4.5.4 */ - if (ecma_is_typedarray (ecma_make_object_value (object_p))) + if (ecma_object_is_typedarray (object_p)) { #if ENABLED (JERRY_ES2015) if (ecma_prop_name_is_symbol (property_name_p)) @@ -826,6 +826,63 @@ ecma_op_object_get (ecma_object_t *object_p, /**< the object */ return ECMA_VALUE_UNDEFINED; } /* ecma_op_object_get */ +/** + * [[Get]] operation of ecma object specified for uint32_t property index + * + * @return ecma value + * Returned value must be freed with ecma_free_value + */ +ecma_value_t +ecma_op_object_get_by_uint32_index (ecma_object_t *object_p, /**< the object */ + uint32_t index) /**< property index */ +{ + if (JERRY_LIKELY (index <= ECMA_DIRECT_STRING_MAX_IMM)) + { + return ecma_op_object_get (object_p, ECMA_CREATE_DIRECT_UINT32_STRING (index)); + } + + ecma_string_t *index_str_p = ecma_new_non_direct_string_from_uint32 (index); + ecma_value_t ret_value = ecma_op_object_get (object_p, index_str_p); + ecma_deref_ecma_string (index_str_p); + + return ret_value; +} /* ecma_op_object_get_by_uint32_index */ + +/** + * Perform ToLength(O.[[Get]]("length")) operation + * + * The property is converted to uint32 during the operation + * + * @return ECMA_VALUE_ERROR - if there was any error during the operation + * ECMA_VALUE_EMPTY - otherwise + */ +ecma_value_t +ecma_op_object_get_length (ecma_object_t *object_p, /**< the object */ + uint32_t *length_p) /**< [out] length value converted to uint32 */ +{ + if (JERRY_LIKELY (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_ARRAY)) + { + *length_p = ecma_array_get_length (object_p); + return ECMA_VALUE_EMPTY; + } + +#if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) + if (ecma_object_is_typedarray (object_p)) + { + *length_p = ecma_typedarray_get_length (object_p); + return ECMA_VALUE_EMPTY; + } +#endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */ + + ecma_value_t len_value = ecma_op_object_get_by_magic_id (object_p, LIT_MAGIC_STRING_LENGTH); + ecma_value_t len_number = ecma_op_to_length (len_value, length_p); + ecma_free_value (len_value); + + JERRY_ASSERT (ECMA_IS_VALUE_ERROR (len_number) || ecma_is_value_empty (len_number)); + + return len_number; +} /* ecma_op_object_get_length */ + /** * [[Get]] operation of ecma object where the property name is a magic string * @@ -1070,7 +1127,7 @@ ecma_op_object_put (ecma_object_t *object_p, /**< the object */ } #if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) /* ES2015 9.4.5.5 */ - if (ecma_is_typedarray (ecma_make_object_value (object_p))) + if (ecma_object_is_typedarray (object_p)) { #if ENABLED (JERRY_ES2015) if (ecma_prop_name_is_symbol (property_name_p)) @@ -1483,7 +1540,7 @@ ecma_op_object_define_own_property (ecma_object_t *obj_p, /**< the object */ #if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) } /* ES2015 9.4.5.3 */ - if (ecma_is_typedarray (ecma_make_object_value (obj_p))) + if (ecma_object_is_typedarray (obj_p)) { #if ENABLED (JERRY_ES2015) if (ecma_prop_name_is_symbol (property_name_p)) @@ -1755,7 +1812,7 @@ ecma_op_object_get_property_names (ecma_object_t *obj_p, /**< object */ case ECMA_OBJECT_TYPE_PSEUDO_ARRAY: { #if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) - if (ecma_is_typedarray (ecma_make_object_value (obj_p))) + if (ecma_object_is_typedarray (obj_p)) { ecma_op_typedarray_list_lazy_property_names (obj_p, prop_names_p); } diff --git a/jerry-core/ecma/operations/ecma-objects.h b/jerry-core/ecma/operations/ecma-objects.h index dcd7979ec..401f52de9 100644 --- a/jerry-core/ecma/operations/ecma-objects.h +++ b/jerry-core/ecma/operations/ecma-objects.h @@ -36,6 +36,8 @@ ecma_value_t ecma_op_object_find_by_uint32_index (ecma_object_t *object_p, uint3 ecma_value_t ecma_op_object_find_by_number_index (ecma_object_t *object_p, ecma_number_t index); ecma_value_t ecma_op_object_get_own_data_prop (ecma_object_t *object_p, ecma_string_t *property_name_p); 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_length (ecma_object_t *object_p, uint32_t *length_p); +ecma_value_t ecma_op_object_get_by_uint32_index (ecma_object_t *object_p, uint32_t index); ecma_value_t ecma_op_object_get_by_magic_id (ecma_object_t *object_p, lit_magic_string_id_t property_id); #if ENABLED (JERRY_ES2015) ecma_value_t ecma_op_object_get_by_symbol_id (ecma_object_t *object_p, lit_magic_string_id_t property_id); diff --git a/jerry-core/ecma/operations/ecma-typedarray-object.c b/jerry-core/ecma/operations/ecma-typedarray-object.c index f7ab193ca..befb59691 100644 --- a/jerry-core/ecma/operations/ecma-typedarray-object.c +++ b/jerry-core/ecma/operations/ecma-typedarray-object.c @@ -466,7 +466,7 @@ ecma_typedarray_helper_get_prototype_id (ecma_typedarray_type_t typedarray_id) / ecma_typedarray_type_t ecma_get_typedarray_id (ecma_object_t *obj_p) /**< typedarray object **/ { - JERRY_ASSERT (ecma_is_typedarray (ecma_make_object_value (obj_p))); + JERRY_ASSERT (ecma_object_is_typedarray (obj_p)); ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; @@ -659,8 +659,6 @@ ecma_op_typedarray_from (ecma_value_t items_val, /**< the source array-like obje uint8_t element_size_shift, /**< the size shift of the element length */ ecma_typedarray_type_t typedarray_id) /**< id of the typedarray */ { - ecma_value_t ret_value = ECMA_VALUE_EMPTY; - /* 3 */ JERRY_ASSERT (ecma_op_is_callable (map_fn_val) || ecma_is_value_undefined (map_fn_val)); @@ -671,20 +669,25 @@ ecma_op_typedarray_from (ecma_value_t items_val, /**< the source array-like obje } /* 10 */ - ECMA_TRY_CATCH (arraylike_object_val, - ecma_op_to_object (items_val), - ret_value); + ecma_value_t arraylike_object_val = ecma_op_to_object (items_val); + + if (ECMA_IS_VALUE_ERROR (arraylike_object_val)) + { + return arraylike_object_val; + } ecma_object_t *arraylike_object_p = ecma_get_object_from_value (arraylike_object_val); /* 12 */ - ECMA_TRY_CATCH (len_value, - ecma_op_object_get_by_magic_id (arraylike_object_p, LIT_MAGIC_STRING_LENGTH), - ret_value); + uint32_t len; + ecma_value_t len_value = ecma_op_object_get_length (arraylike_object_p, &len); - ECMA_OP_TO_NUMBER_TRY_CATCH (len_number, len_value, ret_value); - - uint32_t len = ecma_number_to_uint32 (len_number); + ecma_value_t ret_value = ECMA_VALUE_ERROR; + if (ECMA_IS_VALUE_ERROR (len_value)) + { + ecma_deref_object (arraylike_object_p); + return len_value; + } /* 14 */ ecma_value_t new_typedarray = ecma_typedarray_create_object_with_length (len, @@ -694,91 +697,77 @@ ecma_op_typedarray_from (ecma_value_t items_val, /**< the source array-like obje if (ECMA_IS_VALUE_ERROR (new_typedarray)) { - ret_value = new_typedarray; + ecma_deref_object (arraylike_object_p); + return new_typedarray; } - else + + ecma_object_t *new_typedarray_p = ecma_get_object_from_value (new_typedarray); + ecma_typedarray_info_t info = ecma_typedarray_get_info (new_typedarray_p); + ecma_typedarray_setter_fn_t setter_cb = ecma_get_typedarray_setter_fn (info.id); + ecma_number_t num_var; + + /* 17 */ + for (uint32_t index = 0; index < len; index++) { - ecma_object_t *new_typedarray_p = ecma_get_object_from_value (new_typedarray); - ecma_typedarray_info_t info = ecma_typedarray_get_info (new_typedarray_p); - ecma_typedarray_setter_fn_t setter_cb = ecma_get_typedarray_setter_fn (info.id); - ecma_value_t error = ECMA_VALUE_EMPTY; - ecma_number_t num_var; + /* 17.b */ + ecma_value_t current_value = ecma_op_object_find_by_uint32_index (arraylike_object_p, index); - /* 17 */ - ecma_value_t current_index; - - for (uint32_t index = 0; index < len && ecma_is_value_empty (ret_value); index++) + if (ECMA_IS_VALUE_ERROR (current_value)) { - /* 17.a */ - ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (index); + goto cleanup; + } - /* 17.b */ - ECMA_TRY_CATCH (current_value, ecma_op_object_find (arraylike_object_p, index_str_p), ret_value); - - if (ecma_is_value_found (current_value)) + if (ecma_is_value_found (current_value)) + { + ecma_value_t mapped_value; + if (func_object_p != NULL) { - if (func_object_p != NULL) + /* 17.d 17.f */ + 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_free_value (current_index); + ecma_free_value (current_value); + + if (ECMA_IS_VALUE_ERROR (cb_value)) { - /* 17.d 17.f */ - current_index = ecma_make_uint32_value (index); - ecma_value_t call_args[] = { current_value, current_index}; - - ECMA_TRY_CATCH (mapped_value, ecma_op_function_call (func_object_p, this_val, call_args, 2), ret_value); - - error = ecma_get_number (mapped_value, &num_var); - - if (ECMA_IS_VALUE_ERROR (error)) - { - ret_value = ECMA_VALUE_ERROR; - } - - if (index >= info.length) - { - ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Invalid argument type.")); - } - - ecma_length_t byte_pos = index << info.shift; - setter_cb (info.buffer_p + byte_pos, num_var); - - ECMA_FINALIZE (mapped_value); + goto cleanup; } - else - { - error = ecma_get_number (current_value, &num_var); - if (ECMA_IS_VALUE_ERROR (error)) - { - ret_value = ECMA_VALUE_ERROR; - } - - if (index >= info.length) - { - ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Invalid argument type.")); - } - - ecma_length_t byte_pos = index << info.shift; - setter_cb (info.buffer_p + byte_pos, num_var); - } + mapped_value = cb_value; + } + else + { + mapped_value = current_value; } - ECMA_FINALIZE (current_value); + ecma_value_t mapped_number = ecma_get_number (mapped_value, &num_var); + ecma_free_value (mapped_value); - ecma_deref_ecma_string (index_str_p); - } + if (ECMA_IS_VALUE_ERROR (mapped_number)) + { + goto cleanup; + } - if (ecma_is_value_empty (ret_value)) - { - ret_value = ecma_make_object_value (new_typedarray_p); - } - else - { - ecma_deref_object (new_typedarray_p); + if (index >= info.length) + { + ecma_raise_type_error (ECMA_ERR_MSG ("Invalid argument type.")); + goto cleanup; + } + + ecma_length_t byte_pos = (index << info.shift); + setter_cb (info.buffer_p + byte_pos, num_var); } } - ECMA_OP_TO_NUMBER_FINALIZE (len_number); - ECMA_FINALIZE (len_value); - ECMA_FINALIZE (arraylike_object_val); + ecma_ref_object (new_typedarray_p); + ret_value = ecma_make_object_value (new_typedarray_p); + +cleanup: + ecma_deref_object (new_typedarray_p); + ecma_deref_object (arraylike_object_p); return ret_value; } /* ecma_op_typedarray_from */ @@ -791,7 +780,7 @@ ecma_op_typedarray_from (ecma_value_t items_val, /**< the source array-like obje inline ecma_object_t * JERRY_ATTR_ALWAYS_INLINE ecma_typedarray_get_arraybuffer (ecma_object_t *typedarray_p) /**< the pointer to the typedarray object */ { - JERRY_ASSERT (ecma_is_typedarray (ecma_make_object_value (typedarray_p))); + JERRY_ASSERT (ecma_object_is_typedarray (typedarray_p)); ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) typedarray_p; @@ -806,7 +795,7 @@ ecma_typedarray_get_arraybuffer (ecma_object_t *typedarray_p) /**< the pointer t uint8_t ecma_typedarray_get_element_size_shift (ecma_object_t *typedarray_p) /**< the pointer to the typedarray object */ { - JERRY_ASSERT (ecma_is_typedarray (ecma_make_object_value (typedarray_p))); + JERRY_ASSERT (ecma_object_is_typedarray (typedarray_p)); return ecma_typedarray_helper_get_shift_size (ecma_get_typedarray_id (typedarray_p)); } /* ecma_typedarray_get_element_size_shift */ @@ -820,7 +809,7 @@ ecma_typedarray_get_element_size_shift (ecma_object_t *typedarray_p) /**< the po ecma_length_t ecma_typedarray_get_length (ecma_object_t *typedarray_p) /**< the pointer to the typedarray object */ { - JERRY_ASSERT (ecma_is_typedarray (ecma_make_object_value (typedarray_p))); + JERRY_ASSERT (ecma_object_is_typedarray (typedarray_p)); ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) typedarray_p; @@ -852,7 +841,7 @@ ecma_typedarray_get_length (ecma_object_t *typedarray_p) /**< the pointer to the ecma_length_t ecma_typedarray_get_offset (ecma_object_t *typedarray_p) /**< the pointer to the typedarray object */ { - JERRY_ASSERT (ecma_is_typedarray (ecma_make_object_value (typedarray_p))); + JERRY_ASSERT (ecma_object_is_typedarray (typedarray_p)); ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) typedarray_p; @@ -940,19 +929,20 @@ ecma_op_create_typedarray (const ecma_value_t *arguments_list_p, /**< the arg li } else if (ecma_is_value_object (arguments_list_p[0])) { - if (ecma_is_typedarray (arguments_list_p[0])) + ecma_object_t *obj_p = ecma_get_object_from_value (arguments_list_p[0]); + if (ecma_object_is_typedarray (obj_p)) { /* 22.2.1.3 */ - ecma_object_t *typedarray_p = ecma_get_object_from_value (arguments_list_p[0]); + ecma_object_t *typedarray_p = obj_p; ret = ecma_typedarray_create_object_with_typedarray (typedarray_p, proto_p, element_size_shift, typedarray_id); } - else if (ecma_is_arraybuffer (arguments_list_p[0])) + else if (ecma_object_class_is (obj_p, LIT_MAGIC_STRING_ARRAY_BUFFER_UL)) { /* 22.2.1.5 */ - ecma_object_t *arraybuffer_p = ecma_get_object_from_value (arguments_list_p[0]); + ecma_object_t *arraybuffer_p = obj_p; ecma_value_t arg2 = ((arguments_list_len > 1) ? arguments_list_p[1] : ECMA_VALUE_UNDEFINED); @@ -1043,6 +1033,28 @@ ecma_op_create_typedarray (const ecma_value_t *arguments_list_p, /**< the arg li return ret; } /* ecma_op_create_typedarray */ +/** + * Check if the object is typedarray + * + * @return true - if object is a TypedArray object + * false - otherwise + */ +bool +ecma_object_is_typedarray (ecma_object_t *obj_p) /**< the target object need to be checked */ +{ + JERRY_ASSERT (!ecma_is_lexical_environment (obj_p)); + + if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_PSEUDO_ARRAY) + { + ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; + + return ((ext_object_p->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_TYPEDARRAY) + || (ext_object_p->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_TYPEDARRAY_WITH_INFO)); + } + + return false; +} /* ecma_object_is_typedarray */ + /** * Check if the value is typedarray * @@ -1057,17 +1069,7 @@ ecma_is_typedarray (ecma_value_t value) /**< the target need to be checked */ return false; } - ecma_object_t *obj_p = ecma_get_object_from_value (value); - - if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_PSEUDO_ARRAY) - { - ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; - - return ((ext_object_p->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_TYPEDARRAY) - || (ext_object_p->u.pseudo_array.type == ECMA_PSEUDO_ARRAY_TYPEDARRAY_WITH_INFO)); - } - - return false; + return ecma_object_is_typedarray (ecma_get_object_from_value (value)); } /* ecma_is_typedarray */ /** @@ -1079,7 +1081,7 @@ void ecma_op_typedarray_list_lazy_property_names (ecma_object_t *obj_p, /**< a TypedArray object */ ecma_collection_t *main_collection_p) /**< 'main' collection */ { - JERRY_ASSERT (ecma_is_typedarray (ecma_make_object_value (obj_p))); + JERRY_ASSERT (ecma_object_is_typedarray (obj_p)); ecma_length_t array_length = ecma_typedarray_get_length (obj_p); @@ -1104,7 +1106,7 @@ ecma_op_typedarray_define_index_prop (ecma_object_t *obj_p, /**< a TypedArray ob const ecma_property_descriptor_t *property_desc_p) /**< the description of the prop */ { - JERRY_ASSERT (ecma_is_typedarray (ecma_make_object_value (obj_p))); + JERRY_ASSERT (ecma_object_is_typedarray (obj_p)); ecma_length_t array_length = ecma_typedarray_get_length (obj_p); @@ -1155,13 +1157,12 @@ ecma_op_create_typedarray_with_type_and_length (ecma_object_t *obj_p, /**< Typed * indicates the type */ ecma_length_t array_length) /**< length of the typedarray */ { - JERRY_ASSERT (ecma_is_typedarray (ecma_make_object_value (obj_p))); + JERRY_ASSERT (ecma_object_is_typedarray (obj_p)); #if ENABLED (JERRY_ES2015) ecma_value_t constructor_value = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_CONSTRUCTOR); if (ECMA_IS_VALUE_ERROR (constructor_value) - || !ecma_is_value_object (constructor_value) || !ecma_is_constructor (constructor_value)) { ecma_free_value (constructor_value); diff --git a/jerry-core/ecma/operations/ecma-typedarray-object.h b/jerry-core/ecma/operations/ecma-typedarray-object.h index 3171891a0..770423f11 100644 --- a/jerry-core/ecma/operations/ecma-typedarray-object.h +++ b/jerry-core/ecma/operations/ecma-typedarray-object.h @@ -57,6 +57,7 @@ ecma_value_t ecma_op_create_typedarray (const ecma_value_t *arguments_list_p, ecma_object_t *proto_p, uint8_t element_size_shift, ecma_typedarray_type_t typedarray_id); +bool ecma_object_is_typedarray (ecma_object_t *obj_p); bool ecma_is_typedarray (ecma_value_t target); void ecma_op_typedarray_list_lazy_property_names (ecma_object_t *obj_p, ecma_collection_t *main_collection_p); diff --git a/jerry-core/vm/vm.c b/jerry-core/vm/vm.c index 355359fea..49d23b1c6 100644 --- a/jerry-core/vm/vm.c +++ b/jerry-core/vm/vm.c @@ -570,7 +570,8 @@ 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; - if (!ecma_op_is_callable (func_value)) + 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_MSG ("Expected a function.")); } @@ -654,7 +655,8 @@ opfunc_construct (vm_frame_ctx_t *frame_ctx_p) /**< frame context */ ecma_value_t constructor_value = stack_top_p[-1]; ecma_value_t completion_value; - if (!ecma_is_constructor (constructor_value)) + if (!ecma_is_value_object (constructor_value) + || !ecma_object_is_constructor (ecma_get_object_from_value (constructor_value))) { completion_value = ecma_raise_type_error (ECMA_ERR_MSG ("Expected a constructor.")); }