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 ab907e8cb..fd863f1b7 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.c @@ -35,6 +35,48 @@ #define ECMA_BUILTINS_INTERNAL #include "ecma-builtins-internal.h" +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_ARRAY_PROTOTYPE_ROUTINE_START = ECMA_BUILTIN_ID__COUNT - 1, + /* Note: these 2 routine ids must be in this order */ + ECMA_ARRAY_PROTOTYPE_TO_STRING, + ECMA_ARRAY_PROTOTYPE_CONCAT, + ECMA_ARRAY_PROTOTYPE_TO_LOCALE_STRING, + ECMA_ARRAY_PROTOTYPE_JOIN, + ECMA_ARRAY_PROTOTYPE_POP, + ECMA_ARRAY_PROTOTYPE_PUSH, + ECMA_ARRAY_PROTOTYPE_REVERSE, + ECMA_ARRAY_PROTOTYPE_SHIFT, + ECMA_ARRAY_PROTOTYPE_SLICE, + ECMA_ARRAY_PROTOTYPE_SORT, + ECMA_ARRAY_PROTOTYPE_SPLICE, + ECMA_ARRAY_PROTOTYPE_UNSHIFT, + ECMA_ARRAY_PROTOTYPE_INDEX_OF, + ECMA_ARRAY_PROTOTYPE_LAST_INDEX_OF, + /* Note these 3 routines must be in this order */ + ECMA_ARRAY_PROTOTYPE_EVERY, + ECMA_ARRAY_PROTOTYPE_SOME, + ECMA_ARRAY_PROTOTYPE_FOR_EACH, + ECMA_ARRAY_PROTOTYPE_MAP, + ECMA_ARRAY_PROTOTYPE_FILTER, + /* Note these 2 routines must be in this order */ + ECMA_ARRAY_PROTOTYPE_REDUCE, + ECMA_ARRAY_PROTOTYPE_REDUCE_RIGHT, + ECMA_ARRAY_PROTOTYPE_FIND, + ECMA_ARRAY_PROTOTYPE_ENTRIES, + ECMA_ARRAY_PROTOTYPE_VALUES, + ECMA_ARRAY_PROTOTYPE_KEYS, + ECMA_ARRAY_PROTOTYPE_SYMBOL_ITERATOR, +}; + #define BUILTIN_INC_HEADER_NAME "ecma-builtin-array-prototype.inc.h" #define BUILTIN_UNDERSCORED_ID array_prototype #include "ecma-builtin-internal-routines-template.inc.h" @@ -81,37 +123,31 @@ ecma_builtin_array_prototype_helper_set_length (ecma_object_t *object, /**< obje * Returned value must be freed with ecma_free_value. */ static ecma_value_t -ecma_builtin_array_prototype_object_to_string (ecma_value_t this_arg) /**< this argument */ +ecma_builtin_array_prototype_object_to_string (ecma_value_t this_arg, /**< this argument */ + ecma_object_t *obj_p) /**< array object */ + { - ecma_value_t ret_value = ECMA_VALUE_EMPTY; - - /* 1. */ - ECMA_TRY_CATCH (obj_this_value, - ecma_op_to_object (this_arg), - ret_value); - - ecma_object_t *obj_p = ecma_get_object_from_value (obj_this_value); - /* 2. */ - ECMA_TRY_CATCH (join_value, - ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_JOIN), - ret_value); + ecma_value_t join_value = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_JOIN); + + if (ECMA_IS_VALUE_ERROR (join_value)) + { + return join_value; + } if (!ecma_op_is_callable (join_value)) { /* 3. */ - ret_value = ecma_builtin_helper_object_to_string (this_arg); - } - else - { - /* 4. */ - ecma_object_t *join_func_obj_p = ecma_get_object_from_value (join_value); - - ret_value = ecma_op_function_call (join_func_obj_p, this_arg, NULL, 0); + ecma_free_value (join_value); + return ecma_builtin_helper_object_to_string (this_arg); } - ECMA_FINALIZE (join_value); - ECMA_FINALIZE (obj_this_value); + /* 4. */ + ecma_object_t *join_func_obj_p = ecma_get_object_from_value (join_value); + + ecma_value_t ret_value = ecma_op_function_call (join_func_obj_p, this_arg, NULL, 0); + + ecma_deref_object (join_func_obj_p); return ret_value; } /* ecma_builtin_array_prototype_object_to_string */ @@ -126,78 +162,54 @@ ecma_builtin_array_prototype_object_to_string (ecma_value_t this_arg) /**< this * Returned value must be freed with ecma_free_value. */ static ecma_value_t -ecma_builtin_array_prototype_object_to_locale_string (ecma_value_t this_arg) /**< this argument */ +ecma_builtin_array_prototype_object_to_locale_string (ecma_object_t *obj_p, /**< array object */ + uint32_t length) /**< array object's length */ { - ecma_value_t ret_value = ECMA_VALUE_EMPTY; - - /* 1. */ - ECMA_TRY_CATCH (obj_value, - ecma_op_to_object (this_arg), - ret_value); - - ecma_object_t *obj_p = ecma_get_object_from_value (obj_value); - - /* 2. */ - ECMA_TRY_CATCH (length_value, - ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_LENGTH), - ret_value); - - /* 3. */ - ECMA_OP_TO_NUMBER_TRY_CATCH (length_number, - length_value, - ret_value); - - uint32_t length = ecma_number_to_uint32 (length_number); - - /* 5. */ if (length == 0) { - ret_value = ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); + return ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); + } + + /* 7-8. */ + ecma_value_t first_value = ecma_builtin_helper_get_to_locale_string_at_index (obj_p, 0); + + if (ECMA_IS_VALUE_ERROR (first_value)) + { + return first_value; + } + + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + ecma_string_t *return_string_p = ecma_get_string_from_value (first_value); + ecma_ref_ecma_string (return_string_p); + + /* 9-10. */ + for (uint32_t k = 1; ecma_is_value_empty (ret_value) && (k < length); k++) + { + /* 4. Implementation-defined: set the separator to a single comma character. */ + return_string_p = ecma_append_magic_string_to_string (return_string_p, + LIT_MAGIC_STRING_COMMA_CHAR); + + ECMA_TRY_CATCH (next_string_value, + ecma_builtin_helper_get_to_locale_string_at_index (obj_p, k), + ret_value); + + ecma_string_t *next_string_p = ecma_get_string_from_value (next_string_value); + return_string_p = ecma_concat_ecma_strings (return_string_p, next_string_p); + + ECMA_FINALIZE (next_string_value); + } + + if (ecma_is_value_empty (ret_value)) + { + ret_value = ecma_make_string_value (return_string_p); } else { - /* 7-8. */ - ECMA_TRY_CATCH (first_value, - ecma_builtin_helper_get_to_locale_string_at_index (obj_p, 0), - ret_value); - - ecma_string_t *return_string_p = ecma_get_string_from_value (first_value); - ecma_ref_ecma_string (return_string_p); - - /* 9-10. */ - for (uint32_t k = 1; ecma_is_value_empty (ret_value) && (k < length); k++) - { - /* 4. Implementation-defined: set the separator to a single comma character. */ - return_string_p = ecma_append_magic_string_to_string (return_string_p, - LIT_MAGIC_STRING_COMMA_CHAR); - - ECMA_TRY_CATCH (next_string_value, - ecma_builtin_helper_get_to_locale_string_at_index (obj_p, k), - ret_value); - - ecma_string_t *next_string_p = ecma_get_string_from_value (next_string_value); - return_string_p = ecma_concat_ecma_strings (return_string_p, next_string_p); - - ECMA_FINALIZE (next_string_value); - } - - if (ecma_is_value_empty (ret_value)) - { - ret_value = ecma_make_string_value (return_string_p); - } - else - { - ecma_deref_ecma_string (return_string_p); - } - - ECMA_FINALIZE (first_value); + ecma_deref_ecma_string (return_string_p); } - ECMA_OP_TO_NUMBER_FINALIZE (length_number); - - ECMA_FINALIZE (length_value); - ECMA_FINALIZE (obj_value); + ecma_free_value (first_value); return ret_value; } /* ecma_builtin_array_prototype_object_to_locale_string */ @@ -212,25 +224,16 @@ ecma_builtin_array_prototype_object_to_locale_string (ecma_value_t this_arg) /** * Returned value must be freed with ecma_free_value. */ static ecma_value_t -ecma_builtin_array_prototype_object_concat (ecma_value_t this_arg, /**< this argument */ - const ecma_value_t args[], /**< arguments list */ - ecma_length_t args_number) /**< number of arguments */ +ecma_builtin_array_prototype_object_concat (const ecma_value_t args[], /**< arguments list */ + ecma_length_t args_number, /**< number of arguments */ + ecma_object_t *obj_p) /**< array object */ { - ecma_value_t ret_value = ECMA_VALUE_EMPTY; - - /* 1. */ - ECMA_TRY_CATCH (obj_this, - ecma_op_to_object (this_arg), - ret_value); - /* 2. */ #ifndef CONFIG_DISABLE_ES2015_CLASS - ecma_object_t *obj_p = ecma_get_object_from_value (obj_this); ecma_value_t new_array = ecma_op_create_array_object_by_constructor (NULL, 0, false, obj_p); if (ECMA_IS_VALUE_ERROR (new_array)) { - ecma_free_value (obj_this); return new_array; } #else /* CONFIG_DISABLE_ES2015_CLASS */ @@ -241,9 +244,11 @@ ecma_builtin_array_prototype_object_concat (ecma_value_t this_arg, /**< this arg ecma_object_t *new_array_p = ecma_get_object_from_value (new_array); uint32_t new_length = 0; + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + /* 5.b - 5.c for this_arg */ ECMA_TRY_CATCH (concat_this_value, - ecma_builtin_helper_array_concat_value (new_array_p, &new_length, obj_this), + ecma_builtin_helper_array_concat_value (new_array_p, &new_length, ecma_make_object_value (obj_p)), ret_value); /* 5. */ @@ -272,8 +277,6 @@ ecma_builtin_array_prototype_object_concat (ecma_value_t this_arg, /**< this arg ecma_free_value (new_array); } - ECMA_FINALIZE (obj_this); - return ret_value; } /* ecma_builtin_array_prototype_object_concat */ @@ -345,88 +348,67 @@ ecma_op_array_get_to_string_at_index (ecma_object_t *obj_p, /**< this object */ * Returned value must be freed with ecma_free_value. */ static ecma_value_t -ecma_builtin_array_prototype_join (ecma_value_t this_arg, /**< this argument */ - ecma_value_t separator_arg) /**< separator argument */ +ecma_builtin_array_prototype_join (ecma_value_t separator_arg, /**< separator argument */ + ecma_object_t *obj_p, /**< array object */ + uint32_t length) /**< array object's length */ { ecma_value_t ret_value = ECMA_VALUE_EMPTY; - /* 1. */ - ECMA_TRY_CATCH (obj_value, - ecma_op_to_object (this_arg), - ret_value); - - ecma_object_t *obj_p = ecma_get_object_from_value (obj_value); - - /* 2. */ - ECMA_TRY_CATCH (length_value, - ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_LENGTH), - ret_value); - - ECMA_OP_TO_NUMBER_TRY_CATCH (length_number, - length_value, - ret_value); - - /* 3. */ - uint32_t length = ecma_number_to_uint32 (length_number); - /* 4-5. */ - ECMA_TRY_CATCH (separator_value, - ecma_op_array_get_separator_string (separator_arg), - ret_value); + ecma_value_t separator_value = ecma_op_array_get_separator_string (separator_arg); + + if (ECMA_IS_VALUE_ERROR (separator_value)) + { + return separator_value; + } + + ecma_string_t *separator_string_p = ecma_get_string_from_value (separator_value); if (length == 0) { /* 6. */ - ret_value = ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); + ecma_deref_ecma_string (separator_string_p); + return ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY); + } + + /* 7-8. */ + ECMA_TRY_CATCH (first_value, + ecma_op_array_get_to_string_at_index (obj_p, 0), + ret_value); + + ecma_string_t *return_string_p = ecma_get_string_from_value (first_value); + ecma_ref_ecma_string (return_string_p); + + /* 9-10. */ + for (uint32_t k = 1; ecma_is_value_empty (ret_value) && (k < length); k++) + { + /* 10.a */ + return_string_p = ecma_concat_ecma_strings (return_string_p, separator_string_p); + + /* 10.b, 10.c */ + ECMA_TRY_CATCH (next_string_value, + ecma_op_array_get_to_string_at_index (obj_p, k), + ret_value); + + /* 10.d */ + ecma_string_t *next_string_p = ecma_get_string_from_value (next_string_value); + return_string_p = ecma_concat_ecma_strings (return_string_p, next_string_p); + + ECMA_FINALIZE (next_string_value); + } + + if (ecma_is_value_empty (ret_value)) + { + ret_value = ecma_make_string_value (return_string_p); } else { - ecma_string_t *separator_string_p = ecma_get_string_from_value (separator_value); - - /* 7-8. */ - ECMA_TRY_CATCH (first_value, - ecma_op_array_get_to_string_at_index (obj_p, 0), - ret_value); - - ecma_string_t *return_string_p = ecma_get_string_from_value (first_value); - ecma_ref_ecma_string (return_string_p); - - /* 9-10. */ - for (uint32_t k = 1; ecma_is_value_empty (ret_value) && (k < length); k++) - { - /* 10.a */ - return_string_p = ecma_concat_ecma_strings (return_string_p, separator_string_p); - - /* 10.b, 10.c */ - ECMA_TRY_CATCH (next_string_value, - ecma_op_array_get_to_string_at_index (obj_p, k), - ret_value); - - /* 10.d */ - ecma_string_t *next_string_p = ecma_get_string_from_value (next_string_value); - return_string_p = ecma_concat_ecma_strings (return_string_p, next_string_p); - - ECMA_FINALIZE (next_string_value); - } - - if (ecma_is_value_empty (ret_value)) - { - ret_value = ecma_make_string_value (return_string_p); - } - else - { - ecma_deref_ecma_string (return_string_p); - } - - ECMA_FINALIZE (first_value); + ecma_deref_ecma_string (return_string_p); } - ECMA_FINALIZE (separator_value); + ECMA_FINALIZE (first_value); - ECMA_OP_TO_NUMBER_FINALIZE (length_number); - - ECMA_FINALIZE (length_value); - ECMA_FINALIZE (obj_value); + ecma_free_value (separator_value); return ret_value; } /* ecma_builtin_array_prototype_join */ @@ -441,69 +423,55 @@ ecma_builtin_array_prototype_join (ecma_value_t this_arg, /**< this argument */ * Returned value must be freed with ecma_free_value. */ static ecma_value_t -ecma_builtin_array_prototype_object_pop (ecma_value_t this_arg) /**< this argument */ +ecma_builtin_array_prototype_object_pop (ecma_object_t *obj_p, /**< array object */ + uint32_t len) /**< array object's length */ { - ecma_value_t ret_value = ECMA_VALUE_EMPTY; - - /* 1. */ - ECMA_TRY_CATCH (obj_this, - ecma_op_to_object (this_arg), - ret_value); - - ecma_object_t *obj_p = ecma_get_object_from_value (obj_this); - - /* 2. */ - ECMA_TRY_CATCH (len_value, - ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_LENGTH), - ret_value); - - ECMA_OP_TO_NUMBER_TRY_CATCH (len_number, len_value, ret_value); - - /* 3. */ - uint32_t len = ecma_number_to_uint32 (len_number); - - /* 4. */ + /* 4. */ if (len == 0) { /* 4.a */ - ECMA_TRY_CATCH (set_length_value, - ecma_builtin_array_prototype_helper_set_length (obj_p, ECMA_NUMBER_ZERO), - ret_value); + ecma_value_t set_length_value = ecma_builtin_array_prototype_helper_set_length (obj_p, ECMA_NUMBER_ZERO); + + if (ECMA_IS_VALUE_ERROR (set_length_value)) + { + return set_length_value; + } + + ecma_free_value (set_length_value); /* 4.b */ - ret_value = ECMA_VALUE_UNDEFINED; - - ECMA_FINALIZE (set_length_value) + return ECMA_VALUE_UNDEFINED; } - else + + /* 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); + + if (ECMA_IS_VALUE_ERROR (get_value)) { - len--; - /* 5.a */ - ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (len); - - /* 5.b */ - ECMA_TRY_CATCH (get_value, ecma_op_object_get (obj_p, index_str_p), ret_value); - - /* 5.c */ - ECMA_TRY_CATCH (del_value, ecma_op_object_delete (obj_p, index_str_p, true), ret_value); - - /* 5.d */ - ECMA_TRY_CATCH (set_length_value, - ecma_builtin_array_prototype_helper_set_length (obj_p, ((ecma_number_t) len)), - ret_value); - - ret_value = ecma_copy_value (get_value); - - ECMA_FINALIZE (set_length_value); - ECMA_FINALIZE (del_value); - ECMA_FINALIZE (get_value); - - ecma_deref_ecma_string (index_str_p); + return get_value; } - ECMA_OP_TO_NUMBER_FINALIZE (len_number); - ECMA_FINALIZE (len_value); - ECMA_FINALIZE (obj_this); + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + + /* 5.c */ + ECMA_TRY_CATCH (del_value, ecma_op_object_delete (obj_p, index_str_p, true), ret_value); + + /* 5.d */ + ECMA_TRY_CATCH (set_length_value, + ecma_builtin_array_prototype_helper_set_length (obj_p, ((ecma_number_t) len)), + ret_value); + + ret_value = ecma_copy_value (get_value); + + ECMA_FINALIZE (set_length_value); + ECMA_FINALIZE (del_value); + + ecma_free_value (get_value); + ecma_deref_ecma_string (index_str_p); + return ret_value; } /* ecma_builtin_array_prototype_object_pop */ @@ -518,26 +486,14 @@ ecma_builtin_array_prototype_object_pop (ecma_value_t this_arg) /**< this argume * Returned value must be freed with ecma_free_value. */ static ecma_value_t -ecma_builtin_array_prototype_object_push (ecma_value_t this_arg, /**< this argument */ - const ecma_value_t *argument_list_p, /**< arguments list */ - ecma_length_t arguments_number) /**< number of arguments */ +ecma_builtin_array_prototype_object_push (const ecma_value_t *argument_list_p, /**< arguments list */ + ecma_length_t arguments_number, /**< number of arguments */ + ecma_object_t *obj_p, /**< array object */ + uint32_t length) /**< array object's length */ { ecma_value_t ret_value = ECMA_VALUE_EMPTY; - /* 1. */ - ECMA_TRY_CATCH (obj_this_value, ecma_op_to_object (this_arg), ret_value); - - ecma_object_t *obj_p = ecma_get_object_from_value (obj_this_value); - - /* 2. */ - ECMA_TRY_CATCH (length_value, - ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_LENGTH), - ret_value); - - /* 3. */ - ECMA_OP_TO_NUMBER_TRY_CATCH (length_var, length_value, ret_value); - - ecma_number_t n = ((ecma_number_t) ecma_number_to_uint32 (length_var)); + ecma_number_t n = (ecma_number_t) length; /* 5. */ for (uint32_t index = 0; @@ -568,11 +524,6 @@ ecma_builtin_array_prototype_object_push (ecma_value_t this_arg, /**< this argum ECMA_FINALIZE (set_length_value) } - ECMA_OP_TO_NUMBER_FINALIZE (length_var); - - ECMA_FINALIZE (length_value); - ECMA_FINALIZE (obj_this_value); - return ret_value; } /* ecma_builtin_array_prototype_object_push */ @@ -586,28 +537,13 @@ ecma_builtin_array_prototype_object_push (ecma_value_t this_arg, /**< this argum * Returned value must be freed with ecma_free_value. */ static ecma_value_t -ecma_builtin_array_prototype_object_reverse (ecma_value_t this_arg) /**< this argument */ +ecma_builtin_array_prototype_object_reverse (ecma_value_t this_arg, /**< this argument */ + ecma_object_t *obj_p, /**< array object */ + uint32_t len) /**< array object's length */ { - ecma_value_t ret_value = ECMA_VALUE_EMPTY; - - /* 1. */ - ECMA_TRY_CATCH (obj_this, - ecma_op_to_object (this_arg), - ret_value); - - ecma_object_t *obj_p = ecma_get_object_from_value (obj_this); - - /* 2. */ - ECMA_TRY_CATCH (len_value, - ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_LENGTH), - ret_value); - - /* 3. */ - ECMA_OP_TO_NUMBER_TRY_CATCH (len_number, len_value, ret_value); - uint32_t len = ecma_number_to_uint32 (len_number); - /* 4. */ uint32_t middle = len / 2; + ecma_value_t ret_value = ECMA_VALUE_EMPTY; /* 5-6. */ for (uint32_t lower = 0; lower < middle && ecma_is_value_empty (ret_value); lower++) @@ -660,13 +596,9 @@ ecma_builtin_array_prototype_object_reverse (ecma_value_t this_arg) /**< this ar if (ecma_is_value_empty (ret_value)) { /* 7. */ - ret_value = ecma_copy_value (obj_this); + return ecma_copy_value (this_arg); } - ECMA_OP_TO_NUMBER_FINALIZE (len_number); - ECMA_FINALIZE (len_value); - ECMA_FINALIZE (obj_this); - return ret_value; } /* ecma_builtin_array_prototype_object_reverse */ @@ -680,102 +612,86 @@ ecma_builtin_array_prototype_object_reverse (ecma_value_t this_arg) /**< this ar * Returned value must be freed with ecma_free_value. */ static ecma_value_t -ecma_builtin_array_prototype_object_shift (ecma_value_t this_arg) /**< this argument */ +ecma_builtin_array_prototype_object_shift (ecma_object_t *obj_p, /**< array object */ + uint32_t len) /**< array object's length */ { - ecma_value_t ret_value = ECMA_VALUE_EMPTY; - - /* 1. */ - ECMA_TRY_CATCH (obj_this, - ecma_op_to_object (this_arg), - ret_value); - - ecma_object_t *obj_p = ecma_get_object_from_value (obj_this); - - /* 2. */ - ECMA_TRY_CATCH (len_value, - ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_LENGTH), - ret_value); - - ECMA_OP_TO_NUMBER_TRY_CATCH (len_number, len_value, ret_value); - - /* 3. */ - uint32_t len = ecma_number_to_uint32 (len_number); - /* 4. */ if (len == 0) { - ECMA_TRY_CATCH (set_length_value, - ecma_builtin_array_prototype_helper_set_length (obj_p, ECMA_NUMBER_ZERO), - ret_value); + ecma_value_t set_length_value = ecma_builtin_array_prototype_helper_set_length (obj_p, ECMA_NUMBER_ZERO); - ret_value = ECMA_VALUE_UNDEFINED; + if (ECMA_IS_VALUE_ERROR (set_length_value)) + { + return set_length_value; + } + + ecma_free_value (set_length_value); + + return ECMA_VALUE_UNDEFINED; + } + + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + + /* 5. */ + ecma_value_t first_value = ecma_op_object_get (obj_p, ecma_get_ecma_string_from_uint32 (0)); + + if (ECMA_IS_VALUE_ERROR (first_value)) + { + return first_value; + } + + /* 6. and 7. */ + for (uint32_t k = 1; k < len && ecma_is_value_empty (ret_value); k++) + { + /* 7.a */ + ecma_string_t *from_str_p = ecma_new_ecma_string_from_uint32 (k); + /* 7.b */ + ecma_string_t *to_str_p = ecma_new_ecma_string_from_uint32 (k - 1); + + /* 7.c */ + ECMA_TRY_CATCH (curr_value, ecma_op_object_find (obj_p, from_str_p), ret_value); + + if (ecma_is_value_found (curr_value)) + { + /* 7.d.i, 7.d.ii */ + ECMA_TRY_CATCH (put_value, ecma_op_object_put (obj_p, to_str_p, curr_value, true), ret_value); + + ECMA_FINALIZE (put_value); + } + else + { + /* 7.e.i */ + ECMA_TRY_CATCH (del_value, ecma_op_object_delete (obj_p, to_str_p, true), ret_value); + ECMA_FINALIZE (del_value); + } + + ECMA_FINALIZE (curr_value); + + ecma_deref_ecma_string (to_str_p); + ecma_deref_ecma_string (from_str_p); + } + + if (ecma_is_value_empty (ret_value)) + { + len--; + ecma_string_t *len_str_p = ecma_new_ecma_string_from_uint32 (len); + + /* 8. */ + ECMA_TRY_CATCH (del_value, ecma_op_object_delete (obj_p, len_str_p, true), ret_value); + + /* 9. */ + ECMA_TRY_CATCH (set_length_value, + ecma_builtin_array_prototype_helper_set_length (obj_p, ((ecma_number_t) len)), + ret_value); + /* 10. */ + ret_value = ecma_copy_value (first_value); ECMA_FINALIZE (set_length_value); - } - else - { - /* 5. */ - ECMA_TRY_CATCH (first_value, - ecma_op_object_get (obj_p, ecma_get_ecma_string_from_uint32 (0)), - ret_value); - - /* 6. and 7. */ - for (uint32_t k = 1; k < len && ecma_is_value_empty (ret_value); k++) - { - /* 7.a */ - ecma_string_t *from_str_p = ecma_new_ecma_string_from_uint32 (k); - /* 7.b */ - ecma_string_t *to_str_p = ecma_new_ecma_string_from_uint32 (k - 1); - - /* 7.c */ - ECMA_TRY_CATCH (curr_value, ecma_op_object_find (obj_p, from_str_p), ret_value); - - if (ecma_is_value_found (curr_value)) - { - /* 7.d.i, 7.d.ii */ - ECMA_TRY_CATCH (put_value, ecma_op_object_put (obj_p, to_str_p, curr_value, true), ret_value); - - ECMA_FINALIZE (put_value); - } - else - { - /* 7.e.i */ - ECMA_TRY_CATCH (del_value, ecma_op_object_delete (obj_p, to_str_p, true), ret_value); - ECMA_FINALIZE (del_value); - } - - ECMA_FINALIZE (curr_value); - - ecma_deref_ecma_string (to_str_p); - ecma_deref_ecma_string (from_str_p); - } - - if (ecma_is_value_empty (ret_value)) - { - len--; - ecma_string_t *len_str_p = ecma_new_ecma_string_from_uint32 (len); - - /* 8. */ - ECMA_TRY_CATCH (del_value, ecma_op_object_delete (obj_p, len_str_p, true), ret_value); - - /* 9. */ - ECMA_TRY_CATCH (set_length_value, - ecma_builtin_array_prototype_helper_set_length (obj_p, ((ecma_number_t) len)), - ret_value); - /* 10. */ - ret_value = ecma_copy_value (first_value); - - ECMA_FINALIZE (set_length_value); - ECMA_FINALIZE (del_value); - ecma_deref_ecma_string (len_str_p); - } - - ECMA_FINALIZE (first_value); + ECMA_FINALIZE (del_value); + ecma_deref_ecma_string (len_str_p); } - ECMA_OP_TO_NUMBER_FINALIZE (len_number); - ECMA_FINALIZE (len_value); - ECMA_FINALIZE (obj_this); + ecma_free_value (first_value); return ret_value; } /* ecma_builtin_array_prototype_object_shift */ @@ -790,29 +706,13 @@ ecma_builtin_array_prototype_object_shift (ecma_value_t this_arg) /**< this argu * Returned value must be freed with ecma_free_value. */ static ecma_value_t -ecma_builtin_array_prototype_object_slice (ecma_value_t this_arg, /**< 'this' argument */ - ecma_value_t arg1, /**< start */ - ecma_value_t arg2) /**< end */ +ecma_builtin_array_prototype_object_slice (ecma_value_t arg1, /**< start */ + ecma_value_t arg2, /**< end */ + ecma_object_t *obj_p, /**< array object */ + uint32_t len) /**< array object's length */ { ecma_value_t ret_value = ECMA_VALUE_EMPTY; - /* 1. */ - ECMA_TRY_CATCH (obj_this, - ecma_op_to_object (this_arg), - ret_value); - - ecma_object_t *obj_p = ecma_get_object_from_value (obj_this); - - ECMA_TRY_CATCH (len_value, - ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_LENGTH), - ret_value); - - /* 3. */ - ECMA_OP_TO_NUMBER_TRY_CATCH (len_number, len_value, ret_value); - - /* 4. */ - const uint32_t len = ecma_number_to_uint32 (len_number); - uint32_t start = 0, end = len; /* 5. */ @@ -844,8 +744,6 @@ ecma_builtin_array_prototype_object_slice (ecma_value_t this_arg, /**< 'this' ar if (ECMA_IS_VALUE_ERROR (new_array)) { - ecma_free_value (len_value); - ecma_free_value (obj_this); return new_array; } #else /* CONFIG_DISABLE_ES2015_CLASS */ @@ -898,10 +796,6 @@ ecma_builtin_array_prototype_object_slice (ecma_value_t this_arg, /**< 'this' ar ecma_free_value (new_array); } - ECMA_OP_TO_NUMBER_FINALIZE (len_number); - ECMA_FINALIZE (len_value); - ECMA_FINALIZE (obj_this); - return ret_value; } /* ecma_builtin_array_prototype_object_slice */ @@ -925,87 +819,76 @@ ecma_builtin_array_prototype_object_sort_compare_helper (ecma_value_t lhs, /**< * compares greater than any other value, undefined property values always * sort to the end of the result, followed by non-existent property values. */ - ecma_value_t ret_value = ECMA_VALUE_EMPTY; - ecma_number_t result = ECMA_NUMBER_ZERO; - bool lhs_is_undef = ecma_is_value_undefined (lhs); bool rhs_is_undef = ecma_is_value_undefined (rhs); if (lhs_is_undef) { - if (rhs_is_undef) - { - result = ECMA_NUMBER_ZERO; - } - else - { - result = ECMA_NUMBER_ONE; - } + return ecma_make_number_value (rhs_is_undef ? ECMA_NUMBER_ZERO : ECMA_NUMBER_ONE); } - else + + if (rhs_is_undef) { - if (rhs_is_undef) + return ecma_make_number_value (ECMA_NUMBER_MINUS_ONE); + } + + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + ecma_number_t result = ECMA_NUMBER_ZERO; + + if (ecma_is_value_undefined (compare_func)) + { + /* Default comparison when no compare_func is passed. */ + ECMA_TRY_CATCH (lhs_value, ecma_op_to_string (lhs), ret_value); + ECMA_TRY_CATCH (rhs_value, ecma_op_to_string (rhs), ret_value); + ecma_string_t *lhs_str_p = ecma_get_string_from_value (lhs_value); + ecma_string_t *rhs_str_p = ecma_get_string_from_value (rhs_value); + + if (ecma_compare_ecma_strings_relational (lhs_str_p, rhs_str_p)) { result = ECMA_NUMBER_MINUS_ONE; } + else if (!ecma_compare_ecma_strings (lhs_str_p, rhs_str_p)) + { + result = ECMA_NUMBER_ONE; + } else { - if (ecma_is_value_undefined (compare_func)) - { - /* Default comparison when no compare_func is passed. */ - ECMA_TRY_CATCH (lhs_value, ecma_op_to_string (lhs), ret_value); - ECMA_TRY_CATCH (rhs_value, ecma_op_to_string (rhs), ret_value); - ecma_string_t *lhs_str_p = ecma_get_string_from_value (lhs_value); - ecma_string_t *rhs_str_p = ecma_get_string_from_value (rhs_value); - - if (ecma_compare_ecma_strings_relational (lhs_str_p, rhs_str_p)) - { - result = ECMA_NUMBER_MINUS_ONE; - } - else if (!ecma_compare_ecma_strings (lhs_str_p, rhs_str_p)) - { - result = ECMA_NUMBER_ONE; - } - else - { - result = ECMA_NUMBER_ZERO; - } - - ECMA_FINALIZE (rhs_value); - ECMA_FINALIZE (lhs_value); - } - else - { - /* - * compare_func, if not undefined, will always contain a callable function object. - * We checked this previously, before this function was called. - */ - JERRY_ASSERT (ecma_op_is_callable (compare_func)); - ecma_object_t *comparefn_obj_p = ecma_get_object_from_value (compare_func); - - ecma_value_t compare_args[] = { lhs, rhs }; - - ECMA_TRY_CATCH (call_value, - ecma_op_function_call (comparefn_obj_p, - ECMA_VALUE_UNDEFINED, - compare_args, - 2), - ret_value); - - if (!ecma_is_value_number (call_value)) - { - ECMA_OP_TO_NUMBER_TRY_CATCH (ret_num, call_value, ret_value); - result = ret_num; - ECMA_OP_TO_NUMBER_FINALIZE (ret_num); - } - else - { - result = ecma_get_number_from_value (call_value); - } - - ECMA_FINALIZE (call_value); - } + result = ECMA_NUMBER_ZERO; } + + ECMA_FINALIZE (rhs_value); + ECMA_FINALIZE (lhs_value); + } + else + { + /* + * compare_func, if not undefined, will always contain a callable function object. + * We checked this previously, before this function was called. + */ + JERRY_ASSERT (ecma_op_is_callable (compare_func)); + ecma_object_t *comparefn_obj_p = ecma_get_object_from_value (compare_func); + + ecma_value_t compare_args[] = { lhs, rhs }; + + ECMA_TRY_CATCH (call_value, + ecma_op_function_call (comparefn_obj_p, + ECMA_VALUE_UNDEFINED, + compare_args, + 2), + ret_value); + + if (!ecma_is_value_number (call_value)) + { + ECMA_OP_TO_NUMBER_TRY_CATCH (ret_num, call_value, ret_value); + result = ret_num; + ECMA_OP_TO_NUMBER_FINALIZE (ret_num); + } + else + { + result = ecma_get_number_from_value (call_value); + } + + ECMA_FINALIZE (call_value); } if (ecma_is_value_empty (ret_value)) @@ -1027,7 +910,9 @@ ecma_builtin_array_prototype_object_sort_compare_helper (ecma_value_t lhs, /**< */ static ecma_value_t ecma_builtin_array_prototype_object_sort (ecma_value_t this_arg, /**< this argument */ - ecma_value_t arg1) /**< comparefn */ + ecma_value_t arg1, /**< comparefn */ + ecma_object_t *obj_p, /**< array object */ + uint32_t len) /**< array object's length */ { /* Check if the provided compare function is callable. */ if (!ecma_is_value_undefined (arg1) && !ecma_op_is_callable (arg1)) @@ -1035,31 +920,14 @@ ecma_builtin_array_prototype_object_sort (ecma_value_t this_arg, /**< this argum return ecma_raise_type_error (ECMA_ERR_MSG ("Compare function is not callable.")); } - ecma_value_t ret_value = ECMA_VALUE_EMPTY; - - ECMA_TRY_CATCH (obj_this, - ecma_op_to_object (this_arg), - ret_value); - - ecma_object_t *obj_p = ecma_get_object_from_value (obj_this); - - ECMA_TRY_CATCH (len_value, - ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_LENGTH), - ret_value); - - ECMA_OP_TO_NUMBER_TRY_CATCH (len_number, len_value, ret_value); - - uint32_t len = ecma_number_to_uint32 (len_number); - ecma_collection_header_t *array_index_props_p = ecma_op_object_get_property_names (obj_p, ECMA_LIST_ARRAY_INDICES); uint32_t defined_prop_count = 0; - uint32_t copied_num = 0; ecma_value_t *ecma_value_p = ecma_collection_iterator_init (array_index_props_p); /* Count properties with name that is array index less than len */ - while (ecma_value_p != NULL && ecma_is_value_empty (ret_value)) + while (ecma_value_p != NULL) { ecma_string_t *property_name_p = ecma_get_string_from_value (*ecma_value_p); ecma_value_p = ecma_collection_iterator_next (ecma_value_p); @@ -1073,6 +941,8 @@ ecma_builtin_array_prototype_object_sort (ecma_value_t this_arg, /**< this argum } } + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + uint32_t copied_num = 0; JMEM_DEFINE_LOCAL_ARRAY (values_buffer, defined_prop_count, ecma_value_t); ecma_value_p = ecma_collection_iterator_init (array_index_props_p); @@ -1158,13 +1028,9 @@ ecma_builtin_array_prototype_object_sort (ecma_value_t this_arg, /**< this argum if (ecma_is_value_empty (ret_value)) { - ret_value = ecma_copy_value (this_arg); + return ecma_copy_value (this_arg); } - ECMA_OP_TO_NUMBER_FINALIZE (len_number); - ECMA_FINALIZE (len_value); - ECMA_FINALIZE (obj_this); - return ret_value; } /* ecma_builtin_array_prototype_object_sort */ @@ -1178,38 +1044,16 @@ ecma_builtin_array_prototype_object_sort (ecma_value_t this_arg, /**< this argum * Returned value must be freed with ecma_free_value. */ static ecma_value_t -ecma_builtin_array_prototype_object_splice (ecma_value_t this_arg, /**< this argument */ - const ecma_value_t args[], /**< arguments list */ - ecma_length_t args_number) /**< number of arguments */ +ecma_builtin_array_prototype_object_splice (const ecma_value_t args[], /**< arguments list */ + ecma_length_t args_number, /**< number of arguments */ + ecma_object_t *obj_p, /**< array object */ + uint32_t len) /**< array object's length */ { - ecma_value_t ret_value = ECMA_VALUE_EMPTY; - - /* 1. */ - ECMA_TRY_CATCH (obj_this, - ecma_op_to_object (this_arg), - ret_value); - - ecma_object_t *obj_p = ecma_get_object_from_value (obj_this); - - /* 3. */ - ECMA_TRY_CATCH (len_value, - ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_LENGTH), - ret_value); - - /* 4. */ - ECMA_OP_TO_NUMBER_TRY_CATCH (len_number, - len_value, - ret_value); - - const uint32_t len = ecma_number_to_uint32 (len_number); - #ifndef CONFIG_DISABLE_ES2015_CLASS ecma_value_t new_array = ecma_op_create_array_object_by_constructor (NULL, 0, false, obj_p); if (ECMA_IS_VALUE_ERROR (new_array)) { - ecma_free_value (len_value); - ecma_free_value (obj_this); return new_array; } #else /* CONFIG_DISABLE_ES2015_CLASS */ @@ -1221,6 +1065,7 @@ ecma_builtin_array_prototype_object_splice (ecma_value_t this_arg, /**< this arg uint32_t start = 0; uint32_t delete_count = 0; + ecma_value_t ret_value = ECMA_VALUE_EMPTY; if (args_number > 0) { @@ -1454,10 +1299,6 @@ ecma_builtin_array_prototype_object_splice (ecma_value_t this_arg, /**< this arg ecma_free_value (new_array); } - ECMA_OP_TO_NUMBER_FINALIZE (len_number); - ECMA_FINALIZE (len_value); - ECMA_FINALIZE (obj_this); - return ret_value; } /* ecma_builtin_array_prototype_object_splice */ @@ -1471,29 +1312,13 @@ ecma_builtin_array_prototype_object_splice (ecma_value_t this_arg, /**< this arg * Returned value must be freed with ecma_free_value. */ static ecma_value_t -ecma_builtin_array_prototype_object_unshift (ecma_value_t this_arg, /**< this argument */ - const ecma_value_t args[], /**< arguments list */ - ecma_length_t args_number) /**< number of arguments */ +ecma_builtin_array_prototype_object_unshift (const ecma_value_t args[], /**< arguments list */ + ecma_length_t args_number, /**< number of arguments */ + ecma_object_t *obj_p, /**< array object */ + uint32_t len) /**< array object's length */ { ecma_value_t ret_value = ECMA_VALUE_EMPTY; - /* 1. */ - ECMA_TRY_CATCH (obj_this, - ecma_op_to_object (this_arg), - ret_value); - - ecma_object_t *obj_p = ecma_get_object_from_value (obj_this); - - /* 2. */ - ECMA_TRY_CATCH (len_value, - ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_LENGTH), - ret_value); - - ECMA_OP_TO_NUMBER_TRY_CATCH (len_number, len_value, ret_value); - - /* 3. */ - uint32_t len = ecma_number_to_uint32 (len_number); - /* 5. and 6. */ for (uint32_t k = len; k > 0 && ecma_is_value_empty (ret_value); k--) { @@ -1549,10 +1374,6 @@ ecma_builtin_array_prototype_object_unshift (ecma_value_t this_arg, /**< this ar ECMA_FINALIZE (set_length_value); } - ECMA_OP_TO_NUMBER_FINALIZE (len_number); - ECMA_FINALIZE (len_value); - ECMA_FINALIZE (obj_this); - return ret_value; } /* ecma_builtin_array_prototype_object_unshift */ @@ -1566,80 +1387,57 @@ ecma_builtin_array_prototype_object_unshift (ecma_value_t this_arg, /**< this ar * Returned value must be freed with ecma_free_value. */ static ecma_value_t -ecma_builtin_array_prototype_object_index_of (ecma_value_t this_arg, /**< this argument */ - ecma_value_t arg1, /**< searchElement */ - ecma_value_t arg2) /**< fromIndex */ +ecma_builtin_array_prototype_object_index_of (ecma_value_t arg1, /**< searchElement */ + ecma_value_t arg2, /**< fromIndex */ + ecma_object_t *obj_p, /**< array object */ + uint32_t len) /**< array object's length */ { - ecma_value_t ret_value = ECMA_VALUE_EMPTY; - - /* 1. */ - ECMA_TRY_CATCH (obj_this, - ecma_op_to_object (this_arg), - ret_value); - - ecma_object_t *obj_p = ecma_get_object_from_value (obj_this); - - /* 2. */ - ECMA_TRY_CATCH (len_value, - ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_LENGTH), - ret_value); - - ECMA_OP_TO_NUMBER_TRY_CATCH (len_number, len_value, ret_value); - - /* 3. */ - uint32_t len = ecma_number_to_uint32 (len_number); - /* 4. */ if (len == 0) { - ret_value = ecma_make_integer_value (-1); + return ecma_make_integer_value (-1); } - else + + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + + /* 5. */ + ECMA_OP_TO_NUMBER_TRY_CATCH (arg_from_idx, arg2, ret_value); + + ecma_number_t found_index = ECMA_NUMBER_MINUS_ONE; + + uint32_t from_idx = ecma_builtin_helper_array_index_normalize (arg_from_idx, len); + + /* 6. */ + if (from_idx < len) { - /* 5. */ - ECMA_OP_TO_NUMBER_TRY_CATCH (arg_from_idx, arg2, ret_value); + JERRY_ASSERT (from_idx < len); - ecma_number_t found_index = ECMA_NUMBER_MINUS_ONE; - - uint32_t from_idx = ecma_builtin_helper_array_index_normalize (arg_from_idx, len); - - /* 6. */ - if (from_idx < len) + for (; from_idx < len && found_index < 0 && ecma_is_value_empty (ret_value); from_idx++) { - JERRY_ASSERT (from_idx < len); + ecma_string_t *idx_str_p = ecma_new_ecma_string_from_uint32 (from_idx); - for (; from_idx < len && found_index < 0 && ecma_is_value_empty (ret_value); from_idx++) + /* 9.a */ + ECMA_TRY_CATCH (get_value, ecma_op_object_find (obj_p, idx_str_p), ret_value); + + /* 9.b.i, 9.b.ii */ + if (ecma_is_value_found (get_value) + && ecma_op_strict_equality_compare (arg1, get_value)) { - ecma_string_t *idx_str_p = ecma_new_ecma_string_from_uint32 (from_idx); - - /* 9.a */ - ECMA_TRY_CATCH (get_value, ecma_op_object_find (obj_p, idx_str_p), ret_value); - - /* 9.b.i, 9.b.ii */ - if (ecma_is_value_found (get_value) - && ecma_op_strict_equality_compare (arg1, get_value)) - { - found_index = ((ecma_number_t) from_idx); - } - - ECMA_FINALIZE (get_value); - - ecma_deref_ecma_string (idx_str_p); + found_index = ((ecma_number_t) from_idx); } - } - if (ecma_is_value_empty (ret_value)) - { - ret_value = ecma_make_number_value (found_index); - } + ECMA_FINALIZE (get_value); - ECMA_OP_TO_NUMBER_FINALIZE (arg_from_idx); + ecma_deref_ecma_string (idx_str_p); + } } - ECMA_OP_TO_NUMBER_FINALIZE (len_number); + if (ecma_is_value_empty (ret_value)) + { + ret_value = ecma_make_number_value (found_index); + } - ECMA_FINALIZE (len_value); - ECMA_FINALIZE (obj_this); + ECMA_OP_TO_NUMBER_FINALIZE (arg_from_idx); return ret_value; } /* ecma_builtin_array_prototype_object_index_of */ @@ -1654,133 +1452,110 @@ ecma_builtin_array_prototype_object_index_of (ecma_value_t this_arg, /**< this a * Returned value must be freed with ecma_free_value. */ static ecma_value_t -ecma_builtin_array_prototype_object_last_index_of (ecma_value_t this_arg, /**< this argument */ - const ecma_value_t args[], /**< arguments list */ - ecma_length_t args_number) /**< number of arguments */ +ecma_builtin_array_prototype_object_last_index_of (const ecma_value_t args[], /**< arguments list */ + ecma_length_t args_number, /**< number of arguments */ + ecma_object_t *obj_p, /**< array object */ + uint32_t len) /**< array object's length */ { - ecma_value_t ret_value = ECMA_VALUE_EMPTY; - ecma_value_t search_element = (args_number > 0) ? args[0] : ECMA_VALUE_UNDEFINED; - - /* 1. */ - ECMA_TRY_CATCH (obj_this, - ecma_op_to_object (this_arg), - ret_value); - - ecma_object_t *obj_p = ecma_get_object_from_value (obj_this); - - /* 2. */ - ECMA_TRY_CATCH (len_value, - ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_LENGTH), - ret_value); - - ECMA_OP_TO_NUMBER_TRY_CATCH (len_number, len_value, ret_value); - - /* 3. */ - uint32_t len = ecma_number_to_uint32 (len_number); - - ecma_number_t num = ECMA_NUMBER_MINUS_ONE; - /* 4. */ if (len == 0) { - ret_value = ecma_make_number_value (num); + return ecma_make_integer_value (-1); } - else + + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + uint32_t from_idx = len - 1; + + /* 5. */ + if (args_number > 1) { - uint32_t from_idx = len - 1; + ECMA_OP_TO_NUMBER_TRY_CATCH (arg_from_idx, args[1], ret_value); - /* 5. */ - if (args_number > 1) + if (!ecma_number_is_nan (arg_from_idx)) { - ECMA_OP_TO_NUMBER_TRY_CATCH (arg_from_idx, args[1], ret_value); - if (!ecma_number_is_nan (arg_from_idx)) + if (ecma_number_is_infinity (arg_from_idx)) { - - if (ecma_number_is_infinity (arg_from_idx)) - { - from_idx = ecma_number_is_negative (arg_from_idx) ? (uint32_t) -1 : len - 1; - } - else - { - int32_t int_from_idx = ecma_number_to_int32 (arg_from_idx); - - /* 6. */ - if (int_from_idx >= 0) - { - /* min(int_from_idx, len - 1) */ - if ((uint32_t) int_from_idx > len - 1) - { - from_idx = len - 1; - } - else - { - from_idx = (uint32_t) int_from_idx; - } - } - /* 7. */ - else - { - int_from_idx = -int_from_idx; - - /* We prevent from_idx from being negative, so that we can use an uint32. */ - if ((uint32_t) int_from_idx <= len) - { - from_idx = len - (uint32_t) int_from_idx; - } - else - { - /* - * If from_idx would be negative, we set it to UINT_MAX. See reasoning for this in the comment - * at the for loop below. - */ - from_idx = (uint32_t) -1; - } - } - } + from_idx = ecma_number_is_negative (arg_from_idx) ? (uint32_t) -1 : len - 1; } else { - from_idx = 0; + int32_t int_from_idx = ecma_number_to_int32 (arg_from_idx); + + /* 6. */ + if (int_from_idx >= 0) + { + /* min(int_from_idx, len - 1) */ + if ((uint32_t) int_from_idx > len - 1) + { + from_idx = len - 1; + } + else + { + from_idx = (uint32_t) int_from_idx; + } + } + /* 7. */ + else + { + int_from_idx = -int_from_idx; + + /* We prevent from_idx from being negative, so that we can use an uint32. */ + if ((uint32_t) int_from_idx <= len) + { + from_idx = len - (uint32_t) int_from_idx; + } + else + { + /* + * If from_idx would be negative, we set it to UINT_MAX. See reasoning for this in the comment + * at the for loop below. + */ + from_idx = (uint32_t) -1; + } + } } - - ECMA_OP_TO_NUMBER_FINALIZE (arg_from_idx); } - - /* 8. - * We should break from the loop when from_idx < 0. We can still use an uint32_t for from_idx, and check - * for an underflow instead. This is safe, because from_idx will always start in [0, len - 1], - * and len is in [0, UINT_MAX], so from_idx >= len means we've had an underflow, and should stop. - */ - for (; from_idx < len && num < 0 && ecma_is_value_empty (ret_value); from_idx--) + else { - /* 8.a */ - ecma_string_t *idx_str_p = ecma_new_ecma_string_from_uint32 (from_idx); - - /* 8.a */ - ECMA_TRY_CATCH (get_value, ecma_op_object_find (obj_p, idx_str_p), ret_value); - - /* 8.b.i, 8.b.ii */ - if (ecma_is_value_found (get_value) - && ecma_op_strict_equality_compare (search_element, get_value)) - { - num = ((ecma_number_t) from_idx); - } - - ECMA_FINALIZE (get_value); - - ecma_deref_ecma_string (idx_str_p); + from_idx = 0; } - if (ecma_is_value_empty (ret_value)) - { - ret_value = ecma_make_number_value (num); - } + ECMA_OP_TO_NUMBER_FINALIZE (arg_from_idx); } - ECMA_OP_TO_NUMBER_FINALIZE (len_number); - ECMA_FINALIZE (len_value); - ECMA_FINALIZE (obj_this); + ecma_number_t num = ECMA_NUMBER_MINUS_ONE; + ecma_value_t search_element = (args_number > 0) ? args[0] : ECMA_VALUE_UNDEFINED; + + /* 8. + * We should break from the loop when from_idx < 0. We can still use an uint32_t for from_idx, and check + * for an underflow instead. This is safe, because from_idx will always start in [0, len - 1], + * and len is in [0, UINT_MAX], so from_idx >= len means we've had an underflow, and should stop. + */ + for (; from_idx < len && num < 0 && ecma_is_value_empty (ret_value); from_idx--) + { + /* 8.a */ + ecma_string_t *idx_str_p = ecma_new_ecma_string_from_uint32 (from_idx); + + /* 8.a */ + ECMA_TRY_CATCH (get_value, ecma_op_object_find (obj_p, idx_str_p), ret_value); + + /* 8.b.i, 8.b.ii */ + if (ecma_is_value_found (get_value) + && ecma_op_strict_equality_compare (search_element, get_value)) + { + num = ((ecma_number_t) from_idx); + } + + ECMA_FINALIZE (get_value); + + ecma_deref_ecma_string (idx_str_p); + } + + if (ecma_is_value_empty (ret_value)) + { + ret_value = ecma_make_number_value (num); + } return ret_value; } /* ecma_builtin_array_prototype_object_last_index_of */ @@ -1801,166 +1576,95 @@ typedef enum * the return value stays empty. The common function for 'every', 'some' * and 'forEach' of the Array prototype. * - * @return ecma value - * Returned value must be freed with ecma_free_value. - */ -static ecma_value_t -ecma_builtin_array_apply (ecma_value_t this_arg, /**< this argument */ - ecma_value_t arg1, /**< callbackfn */ - ecma_value_t arg2, /**< thisArg */ - array_routine_mode mode) /**< array routine mode */ - -{ - JERRY_ASSERT (mode < ARRAY_ROUTINE__COUNT); - - ecma_value_t ret_value = ECMA_VALUE_EMPTY; - - /* 1. */ - ECMA_TRY_CATCH (obj_this, - ecma_op_to_object (this_arg), - ret_value); - - ecma_object_t *obj_p = ecma_get_object_from_value (obj_this); - - /* 2. */ - ECMA_TRY_CATCH (len_value, - ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_LENGTH), - ret_value); - - ECMA_OP_TO_NUMBER_TRY_CATCH (len_number, len_value, ret_value); - - /* 3. */ - uint32_t len = ecma_number_to_uint32 (len_number); - - /* 4. */ - if (!ecma_op_is_callable (arg1)) - { - ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Callback function is not callable.")); - } - else - { - ecma_value_t current_index; - ecma_object_t *func_object_p; - - /* We already checked that arg1 is callable, so it will always coerce to an object. */ - ecma_value_t to_object_comp = ecma_op_to_object (arg1); - JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (to_object_comp)); - - func_object_p = ecma_get_object_from_value (to_object_comp); - - /* 7. */ - for (uint32_t index = 0; index < len && ecma_is_value_empty (ret_value); index++) - { - /* 7.a */ - ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (index); - - /* 7.c */ - ECMA_TRY_CATCH (get_value, ecma_op_object_find (obj_p, index_str_p), ret_value); - - if (ecma_is_value_found (get_value)) - { - /* 7.c.i */ - current_index = ecma_make_uint32_value (index); - - ecma_value_t call_args[] = { get_value, current_index, obj_this }; - /* 7.c.ii */ - ECMA_TRY_CATCH (call_value, ecma_op_function_call (func_object_p, arg2, call_args, 3), ret_value); - - /* 7.c.iii */ - if (mode == ARRAY_ROUTINE_EVERY && !ecma_op_to_boolean (call_value)) - { - ret_value = ECMA_VALUE_FALSE; - } - else if (mode == ARRAY_ROUTINE_SOME && ecma_op_to_boolean (call_value)) - { - ret_value = ECMA_VALUE_TRUE; - } - - ECMA_FINALIZE (call_value); - } - - ECMA_FINALIZE (get_value); - - ecma_deref_ecma_string (index_str_p); - } - - ecma_free_value (to_object_comp); - - /* 8. */ - if (ecma_is_value_empty (ret_value)) - { - if (mode == ARRAY_ROUTINE_EVERY) - { - ret_value = ECMA_VALUE_TRUE; - } - else if (mode == ARRAY_ROUTINE_SOME) - { - ret_value = ECMA_VALUE_FALSE; - } - else - { - ret_value = ECMA_VALUE_UNDEFINED; - } - } - } - - ECMA_OP_TO_NUMBER_FINALIZE (len_number); - ECMA_FINALIZE (len_value); - ECMA_FINALIZE (obj_this); - - return ret_value; -} /* ecma_builtin_array_apply */ - -/** - * The Array.prototype object's 'every' routine - * * See also: * ECMA-262 v5, 15.4.4.16 - * - * @return ecma value - * Returned value must be freed with ecma_free_value. - */ -static ecma_value_t -ecma_builtin_array_prototype_object_every (ecma_value_t this_arg, /**< this argument */ - ecma_value_t arg1, /**< callbackfn */ - ecma_value_t arg2) /**< thisArg */ -{ - return ecma_builtin_array_apply (this_arg, arg1, arg2, ARRAY_ROUTINE_EVERY); -} /* ecma_builtin_array_prototype_object_every */ - -/** - * The Array.prototype object's 'some' routine - * - * See also: * ECMA-262 v5, 15.4.4.17 - * - * @return ecma value - * Returned value must be freed with ecma_free_value. - */ -static ecma_value_t -ecma_builtin_array_prototype_object_some (ecma_value_t this_arg, /**< this argument */ - ecma_value_t arg1, /**< callbackfn */ - ecma_value_t arg2) /**< thisArg */ -{ - return ecma_builtin_array_apply (this_arg, arg1, arg2, ARRAY_ROUTINE_SOME); -} /* ecma_builtin_array_prototype_object_some */ - -/** - * The Array.prototype object's 'forEach' routine - * - * See also: * ECMA-262 v5, 15.4.4.18 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t -ecma_builtin_array_prototype_object_for_each (ecma_value_t this_arg, /**< this argument */ - ecma_value_t arg1, /**< callbackfn */ - ecma_value_t arg2) /**< thisArg */ +ecma_builtin_array_apply (ecma_value_t arg1, /**< callbackfn */ + ecma_value_t arg2, /**< thisArg */ + array_routine_mode mode, /**< array routine mode */ + ecma_object_t *obj_p, /**< array object */ + uint32_t len) /**< array object's length */ + { - return ecma_builtin_array_apply (this_arg, arg1, arg2, ARRAY_ROUTINE_FOREACH); -} /* ecma_builtin_array_prototype_object_for_each */ + JERRY_ASSERT (mode < ARRAY_ROUTINE__COUNT); + + /* 4. */ + if (!ecma_op_is_callable (arg1)) + { + return ecma_raise_type_error (ECMA_ERR_MSG ("Callback function is not callable.")); + } + + /* We already checked that arg1 is callable, so it will always coerce to an object. */ + ecma_value_t to_object_comp = ecma_op_to_object (arg1); + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (to_object_comp)); + + ecma_object_t *func_object_p = ecma_get_object_from_value (to_object_comp); + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + ecma_value_t current_index; + + /* 7. */ + for (uint32_t index = 0; index < len && ecma_is_value_empty (ret_value); index++) + { + /* 7.a */ + ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (index); + + /* 7.c */ + ECMA_TRY_CATCH (get_value, ecma_op_object_find (obj_p, index_str_p), ret_value); + + if (ecma_is_value_found (get_value)) + { + /* 7.c.i */ + current_index = ecma_make_uint32_value (index); + + ecma_value_t call_args[] = { get_value, current_index, ecma_make_object_value (obj_p) }; + /* 7.c.ii */ + ECMA_TRY_CATCH (call_value, ecma_op_function_call (func_object_p, arg2, call_args, 3), ret_value); + + /* 7.c.iii */ + if (mode == ARRAY_ROUTINE_EVERY && !ecma_op_to_boolean (call_value)) + { + ret_value = ECMA_VALUE_FALSE; + } + else if (mode == ARRAY_ROUTINE_SOME && ecma_op_to_boolean (call_value)) + { + ret_value = ECMA_VALUE_TRUE; + } + + ECMA_FINALIZE (call_value); + } + + ECMA_FINALIZE (get_value); + + ecma_deref_ecma_string (index_str_p); + } + + ecma_free_value (to_object_comp); + + /* 8. */ + if (ecma_is_value_empty (ret_value)) + { + if (mode == ARRAY_ROUTINE_EVERY) + { + ret_value = ECMA_VALUE_TRUE; + } + else if (mode == ARRAY_ROUTINE_SOME) + { + ret_value = ECMA_VALUE_FALSE; + } + else + { + ret_value = ECMA_VALUE_UNDEFINED; + } + } + + return ret_value; +} /* ecma_builtin_array_apply */ /** * The Array.prototype object's 'map' routine @@ -1972,113 +1676,85 @@ ecma_builtin_array_prototype_object_for_each (ecma_value_t this_arg, /**< this a * Returned value must be freed with ecma_free_value. */ static ecma_value_t -ecma_builtin_array_prototype_object_map (ecma_value_t this_arg, /**< this argument */ - ecma_value_t arg1, /**< callbackfn */ - ecma_value_t arg2) /**< thisArg */ +ecma_builtin_array_prototype_object_map (ecma_value_t arg1, /**< callbackfn */ + ecma_value_t arg2, /**< thisArg */ + ecma_object_t *obj_p, /**< array object */ + uint32_t len) /**< array object's length */ { - ecma_value_t ret_value = ECMA_VALUE_EMPTY; - - /* 1. */ - ECMA_TRY_CATCH (obj_this, - ecma_op_to_object (this_arg), - ret_value); - - ecma_object_t *obj_p = ecma_get_object_from_value (obj_this); - - /* 2. */ - ECMA_TRY_CATCH (len_value, - ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_LENGTH), - ret_value); - - ECMA_OP_TO_NUMBER_TRY_CATCH (len_number, len_value, ret_value); - - /* 3. */ - uint32_t len = ecma_number_to_uint32 (len_number); - /* 4. */ if (!ecma_op_is_callable (arg1)) { - ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Callback function is not callable.")); + return ecma_raise_type_error (ECMA_ERR_MSG ("Callback function is not callable.")); + } + + /* 6. */ +#ifndef CONFIG_DISABLE_ES2015_CLASS + ecma_value_t new_array = ecma_op_create_array_object_by_constructor (NULL, 0, false, obj_p); + + if (ECMA_IS_VALUE_ERROR (new_array)) + { + return new_array; + } +#else /* CONFIG_DISABLE_ES2015_CLASS */ + ecma_value_t new_array = ecma_op_create_array_object (NULL, 0, false); + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (new_array)); +#endif /* !CONFIG_DISABLE_ES2015_CLASS */ + + ecma_object_t *new_array_p = ecma_get_object_from_value (new_array); + + JERRY_ASSERT (ecma_is_value_object (arg1)); + ecma_object_t *func_object_p = ecma_get_object_from_value (arg1); + + /* 7-8. */ + ecma_value_t current_index; + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + + for (uint32_t index = 0; index < len && ecma_is_value_empty (ret_value); index++) + { + /* 8.a */ + ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (index); + + /* 8.b */ + ECMA_TRY_CATCH (current_value, ecma_op_object_find (obj_p, index_str_p), ret_value); + + if (ecma_is_value_found (current_value)) + { + /* 8.c.i, 8.c.ii */ + current_index = ecma_make_uint32_value (index); + ecma_value_t call_args[] = { current_value, current_index, ecma_make_object_value (obj_p) }; + + ECMA_TRY_CATCH (mapped_value, ecma_op_function_call (func_object_p, arg2, call_args, 3), ret_value); + + /* 8.c.iii */ + /* 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 (new_array_p, + index_str_p, + mapped_value, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, + false); /* Failure handling */ + JERRY_ASSERT (ecma_is_value_true (put_comp)); + + ECMA_FINALIZE (mapped_value); + } + + ECMA_FINALIZE (current_value); + + ecma_deref_ecma_string (index_str_p); + } + + if (ecma_is_value_empty (ret_value)) + { + ECMA_TRY_CATCH (set_length_value, + ecma_builtin_array_prototype_helper_set_length (new_array_p, ((ecma_number_t) len)), + ret_value); + ret_value = new_array; + ECMA_FINALIZE (set_length_value); } else { - ecma_object_t *func_object_p; - JERRY_ASSERT (ecma_is_value_object (arg1)); - func_object_p = ecma_get_object_from_value (arg1); - - /* 5. arg2 is simply used as T */ - - /* 6. */ -#ifndef CONFIG_DISABLE_ES2015_CLASS - ecma_value_t new_array = ecma_op_create_array_object_by_constructor (NULL, 0, false, obj_p); - - if (ECMA_IS_VALUE_ERROR (new_array)) - { - ecma_free_value (len_value); - ecma_free_value (obj_this); - return new_array; - } -#else /* CONFIG_DISABLE_ES2015_CLASS */ - ecma_value_t new_array = ecma_op_create_array_object (NULL, 0, false); - JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (new_array)); -#endif /* !CONFIG_DISABLE_ES2015_CLASS */ - - ecma_object_t *new_array_p = ecma_get_object_from_value (new_array); - - /* 7-8. */ - ecma_value_t current_index; - - for (uint32_t index = 0; index < len && ecma_is_value_empty (ret_value); index++) - { - /* 8.a */ - ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (index); - - /* 8.b */ - ECMA_TRY_CATCH (current_value, ecma_op_object_find (obj_p, index_str_p), ret_value); - - if (ecma_is_value_found (current_value)) - { - /* 8.c.i, 8.c.ii */ - current_index = ecma_make_uint32_value (index); - ecma_value_t call_args[] = { current_value, current_index, obj_this }; - - ECMA_TRY_CATCH (mapped_value, ecma_op_function_call (func_object_p, arg2, call_args, 3), ret_value); - - /* 8.c.iii */ - /* 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 (new_array_p, - index_str_p, - mapped_value, - ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, - false); /* Failure handling */ - JERRY_ASSERT (ecma_is_value_true (put_comp)); - - ECMA_FINALIZE (mapped_value); - } - - ECMA_FINALIZE (current_value); - - ecma_deref_ecma_string (index_str_p); - } - - if (ecma_is_value_empty (ret_value)) - { - ECMA_TRY_CATCH (set_length_value, - ecma_builtin_array_prototype_helper_set_length (new_array_p, ((ecma_number_t) len)), - ret_value); - ret_value = new_array; - ECMA_FINALIZE (set_length_value); - } - else - { - ecma_free_value (new_array); - } + ecma_free_value (new_array); } - ECMA_OP_TO_NUMBER_FINALIZE (len_number); - ECMA_FINALIZE (len_value); - ECMA_FINALIZE (obj_this); - return ret_value; } /* ecma_builtin_array_prototype_object_map */ @@ -2092,319 +1768,230 @@ ecma_builtin_array_prototype_object_map (ecma_value_t this_arg, /**< this argume * Returned value must be freed with ecma_free_value. */ static ecma_value_t -ecma_builtin_array_prototype_object_filter (ecma_value_t this_arg, /**< this argument */ - ecma_value_t arg1, /**< callbackfn */ - ecma_value_t arg2) /**< thisArg */ +ecma_builtin_array_prototype_object_filter (ecma_value_t arg1, /**< callbackfn */ + ecma_value_t arg2, /**< thisArg */ + ecma_object_t *obj_p, /**< array object */ + uint32_t len) /**< array object's length */ { - ecma_value_t ret_value = ECMA_VALUE_EMPTY; - - /* 1. */ - ECMA_TRY_CATCH (obj_this, - ecma_op_to_object (this_arg), - ret_value); - - ecma_object_t *obj_p = ecma_get_object_from_value (obj_this); - - /* 2. */ - ECMA_TRY_CATCH (len_value, - ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_LENGTH), - ret_value); - - /* 3. */ - ECMA_OP_TO_NUMBER_TRY_CATCH (len_number, len_value, ret_value); - - uint32_t len = ecma_number_to_uint32 (len_number); - /* 4. */ if (!ecma_op_is_callable (arg1)) { - ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Callback function is not callable.")); + return ecma_raise_type_error (ECMA_ERR_MSG ("Callback function is not callable.")); + } + + /* 6. */ +#ifndef CONFIG_DISABLE_ES2015_CLASS + ecma_value_t new_array = ecma_op_create_array_object_by_constructor (NULL, 0, false, obj_p); + + if (ECMA_IS_VALUE_ERROR (new_array)) + { + return new_array; + } +#else /* CONFIG_DISABLE_ES2015_CLASS */ + ecma_value_t new_array = ecma_op_create_array_object (NULL, 0, false); + JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (new_array)); +#endif /* !CONFIG_DISABLE_ES2015_CLASS */ + + ecma_object_t *new_array_p = ecma_get_object_from_value (new_array); + + /* We already checked that arg1 is callable, so it will always be an object. */ + JERRY_ASSERT (ecma_is_value_object (arg1)); + ecma_object_t *func_object_p = ecma_get_object_from_value (arg1); + + /* 8. */ + uint32_t new_array_index = 0; + ecma_value_t current_index; + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + + /* 9. */ + for (uint32_t index = 0; index < len && ecma_is_value_empty (ret_value); index++) + { + /* 9.a */ + ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (index); + + /* 9.c */ + ECMA_TRY_CATCH (get_value, ecma_op_object_find (obj_p, index_str_p), ret_value); + + if (ecma_is_value_found (get_value)) + { + /* 9.c.i */ + current_index = ecma_make_uint32_value (index); + + ecma_value_t call_args[] = { get_value, current_index, ecma_make_object_value (obj_p) }; + /* 9.c.ii */ + ECMA_TRY_CATCH (call_value, ecma_op_function_call (func_object_p, arg2, call_args, 3), ret_value); + + /* 9.c.iii */ + if (ecma_op_to_boolean (call_value)) + { + ecma_string_t *to_index_string_p = ecma_new_ecma_string_from_uint32 (new_array_index); + + /* 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 (new_array_p, + to_index_string_p, + get_value, + ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, + false); /* Failure handling */ + JERRY_ASSERT (ecma_is_value_true (put_comp)); + + ecma_deref_ecma_string (to_index_string_p); + new_array_index++; + } + + ECMA_FINALIZE (call_value); + } + + ECMA_FINALIZE (get_value); + + ecma_deref_ecma_string (index_str_p); + } + + if (ecma_is_value_empty (ret_value)) + { + /* 10. */ + ret_value = new_array; } else { - ecma_value_t current_index; - ecma_object_t *func_object_p; - - /* 6. */ -#ifndef CONFIG_DISABLE_ES2015_CLASS - ecma_value_t new_array = ecma_op_create_array_object_by_constructor (NULL, 0, false, obj_p); - - if (ECMA_IS_VALUE_ERROR (new_array)) - { - ecma_free_value (len_value); - ecma_free_value (obj_this); - return new_array; - } -#else /* CONFIG_DISABLE_ES2015_CLASS */ - ecma_value_t new_array = ecma_op_create_array_object (NULL, 0, false); - JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (new_array)); -#endif /* !CONFIG_DISABLE_ES2015_CLASS */ - - ecma_object_t *new_array_p = ecma_get_object_from_value (new_array); - - /* We already checked that arg1 is callable, so it will always be an object. */ - JERRY_ASSERT (ecma_is_value_object (arg1)); - func_object_p = ecma_get_object_from_value (arg1); - - /* 8. */ - uint32_t new_array_index = 0; - - /* 9. */ - for (uint32_t index = 0; index < len && ecma_is_value_empty (ret_value); index++) - { - /* 9.a */ - ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (index); - - /* 9.c */ - ECMA_TRY_CATCH (get_value, ecma_op_object_find (obj_p, index_str_p), ret_value); - - if (ecma_is_value_found (get_value)) - { - /* 9.c.i */ - current_index = ecma_make_uint32_value (index); - - ecma_value_t call_args[] = { get_value, current_index, obj_this }; - /* 9.c.ii */ - ECMA_TRY_CATCH (call_value, ecma_op_function_call (func_object_p, arg2, call_args, 3), ret_value); - - /* 9.c.iii */ - if (ecma_op_to_boolean (call_value)) - { - ecma_string_t *to_index_string_p = ecma_new_ecma_string_from_uint32 (new_array_index); - - /* 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 (new_array_p, - to_index_string_p, - get_value, - ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, - false); /* Failure handling */ - JERRY_ASSERT (ecma_is_value_true (put_comp)); - - ecma_deref_ecma_string (to_index_string_p); - new_array_index++; - } - - ECMA_FINALIZE (call_value); - } - - ECMA_FINALIZE (get_value); - - ecma_deref_ecma_string (index_str_p); - } - - if (ecma_is_value_empty (ret_value)) - { - /* 10. */ - ret_value = new_array; - } - else - { - ecma_free_value (new_array); - } + ecma_free_value (new_array); } - ECMA_OP_TO_NUMBER_FINALIZE (len_number); - ECMA_FINALIZE (len_value); - ECMA_FINALIZE (obj_this); - return ret_value; } /* ecma_builtin_array_prototype_object_filter */ /** - * Reduces the Array starting from left or right + * The Array.prototype object's 'reduce' and 'reduceRight' routine * * See also: - * Array.prototype.reduce - * Array.prototype.reduceRight + * ECMA-262 v5, 15.4.4.21 + * ECMA-262 v5, 15.4.4.22 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t -ecma_builtin_array_reduce_from (ecma_value_t this_arg, /**< this argument */ - const ecma_value_t args[], /**< arguments list */ - ecma_length_t args_number, /**< number of arguments */ - bool start_from_left) /**< whether the reduce starts from left or right */ +ecma_builtin_array_reduce_from (ecma_value_t callbackfn, /**< routine's 1st argument */ + ecma_value_t initial_value, /**< routine's 2nd argument */ + ecma_length_t args_number, /**< arguments list length */ + bool start_from_left, /**< whether the reduce starts from left or right */ + ecma_object_t *obj_p, /**< array object */ + uint32_t len) /**< array object's length */ { - ecma_value_t ret_value = ECMA_VALUE_EMPTY; - ecma_value_t callbackfn = (args_number > 0) ? args[0] : ECMA_VALUE_UNDEFINED; - ecma_value_t initial_value = (args_number > 1) ? args[1] : ECMA_VALUE_UNDEFINED; - - /* 1. */ - ECMA_TRY_CATCH (obj_this, - ecma_op_to_object (this_arg), - ret_value); - - ecma_object_t *obj_p = ecma_get_object_from_value (obj_this); - - /* 2. */ - ECMA_TRY_CATCH (len_value, - ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_LENGTH), - ret_value); - - ECMA_OP_TO_NUMBER_TRY_CATCH (len_number, len_value, ret_value); - - /* 3. */ - uint32_t len = ecma_number_to_uint32 (len_number); - /* 4. */ if (!ecma_op_is_callable (callbackfn)) { - ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Callback function is not callable.")); + return ecma_raise_type_error (ECMA_ERR_MSG ("Callback function is not callable.")); + } + + /* 5. */ + if (len == 0 && ecma_is_value_undefined (initial_value)) + { + return ecma_raise_type_error (ECMA_ERR_MSG ("Initial value cannot be undefined.")); + } + + JERRY_ASSERT (ecma_is_value_object (callbackfn)); + ecma_object_t *func_object_p = ecma_get_object_from_value (callbackfn); + + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + ecma_value_t accumulator = ECMA_VALUE_UNDEFINED; + + /* 6. */ + uint32_t index = 0; + const uint32_t last_index = len - 1; + + /* 7.a */ + if (args_number > 1) + { + accumulator = ecma_copy_value (initial_value); } else { - ecma_object_t *func_object_p; + /* 8.a */ + bool k_present = false; - JERRY_ASSERT (ecma_is_value_object (callbackfn)); - func_object_p = ecma_get_object_from_value (callbackfn); - - /* 5. */ - if (len_number == ECMA_NUMBER_ZERO && ecma_is_value_undefined (initial_value)) + /* 8.b */ + while (!k_present && index < len && ecma_is_value_empty (ret_value)) { - ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Initial value cannot be undefined.")); - } - else - { - ecma_value_t accumulator = ECMA_VALUE_UNDEFINED; + /* 8.b.i */ + ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (start_from_left ? index + : last_index - index); + k_present = true; - /* 6. */ - uint32_t index = 0; - const uint32_t last_index = len - 1; + /* 8.b.ii-iii */ + ECMA_TRY_CATCH (current_value, ecma_op_object_find (obj_p, index_str_p), ret_value); - /* 7.a */ - if (args_number > 1) + if (ecma_is_value_found (current_value)) { - accumulator = ecma_copy_value (initial_value); + accumulator = ecma_copy_value (current_value); } else { - /* 8.a */ - bool k_present = false; - - /* 8.b */ - while (!k_present && index < len && ecma_is_value_empty (ret_value)) - { - /* 8.b.i */ - ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (start_from_left ? index - : last_index - index); - k_present = true; - - /* 8.b.ii-iii */ - ECMA_TRY_CATCH (current_value, ecma_op_object_find (obj_p, index_str_p), ret_value); - - if (ecma_is_value_found (current_value)) - { - accumulator = ecma_copy_value (current_value); - } - else - { - k_present = false; - } - - ECMA_FINALIZE (current_value); - - /* 8.b.iv */ - index++; - - ecma_deref_ecma_string (index_str_p); - } - - /* 8.c */ - if (!k_present) - { - ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Missing array element.")); - } - } - /* 9. */ - ecma_value_t current_index; - - for (; index < len && ecma_is_value_empty (ret_value); index++) - { - const uint32_t corrected_index = start_from_left ? index : last_index - index; - - /* 9.a */ - ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (corrected_index); - - /* 9.b */ - ECMA_TRY_CATCH (current_value, ecma_op_object_find (obj_p, index_str_p), ret_value); - - if (ecma_is_value_found (current_value)) - { - /* 9.c.i, 9.c.ii */ - current_index = ecma_make_uint32_value (corrected_index); - ecma_value_t call_args[] = {accumulator, current_value, current_index, obj_this}; - - ECMA_TRY_CATCH (call_value, - ecma_op_function_call (func_object_p, - ECMA_VALUE_UNDEFINED, - call_args, - 4), - ret_value); - - ecma_free_value (accumulator); - accumulator = ecma_copy_value (call_value); - - ECMA_FINALIZE (call_value); - } - - ECMA_FINALIZE (current_value); - - ecma_deref_ecma_string (index_str_p); - - /* 9.d in for loop */ + k_present = false; } - if (ecma_is_value_empty (ret_value)) - { - ret_value = ecma_copy_value (accumulator); - } + ECMA_FINALIZE (current_value); - ecma_free_value (accumulator); + /* 8.b.iv */ + index++; + + ecma_deref_ecma_string (index_str_p); + } + + /* 8.c */ + if (!k_present) + { + ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Missing array element.")); } } + /* 9. */ + ecma_value_t current_index; - ECMA_OP_TO_NUMBER_FINALIZE (len_number); - ECMA_FINALIZE (len_value); - ECMA_FINALIZE (obj_this); + for (; index < len && ecma_is_value_empty (ret_value); index++) + { + const uint32_t corrected_index = start_from_left ? index : last_index - index; + + /* 9.a */ + ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (corrected_index); + + /* 9.b */ + ECMA_TRY_CATCH (current_value, ecma_op_object_find (obj_p, index_str_p), ret_value); + + if (ecma_is_value_found (current_value)) + { + /* 9.c.i, 9.c.ii */ + current_index = ecma_make_uint32_value (corrected_index); + ecma_value_t call_args[] = {accumulator, current_value, current_index, ecma_make_object_value (obj_p)}; + + ECMA_TRY_CATCH (call_value, + ecma_op_function_call (func_object_p, + ECMA_VALUE_UNDEFINED, + call_args, + 4), + ret_value); + + ecma_free_value (accumulator); + accumulator = ecma_copy_value (call_value); + + ECMA_FINALIZE (call_value); + } + + ECMA_FINALIZE (current_value); + + ecma_deref_ecma_string (index_str_p); + + /* 9.d in for loop */ + } + + if (ecma_is_value_empty (ret_value)) + { + ret_value = ecma_copy_value (accumulator); + } + + ecma_free_value (accumulator); return ret_value; } /* ecma_builtin_array_reduce_from */ -/** - * The Array.prototype object's 'reduce' routine - * - * See also: - * ECMA-262 v5, 15.4.4.21 - * - * @return ecma value - * Returned value must be freed with ecma_free_value. - */ -static ecma_value_t -ecma_builtin_array_prototype_object_reduce (ecma_value_t this_arg, /**< this argument */ - const ecma_value_t args[], /**< arguments list */ - ecma_length_t args_number) /**< number of arguments */ -{ - return ecma_builtin_array_reduce_from (this_arg, args, args_number, true); -} /* ecma_builtin_array_prototype_object_reduce */ - -/** - * The Array.prototype object's 'reduceRight' routine - * - * See also: - * ECMA-262 v5, 15.4.4.22 - * - * @return ecma value - * Returned value must be freed with ecma_free_value. - */ -static ecma_value_t -ecma_builtin_array_prototype_object_reduce_right (ecma_value_t this_arg, /**< this argument */ - const ecma_value_t args[], /**< arguments list */ - ecma_length_t args_number) /**< number of arguments */ -{ - return ecma_builtin_array_reduce_from (this_arg, args, args_number, false); -} /* ecma_builtin_array_prototype_object_reduce_right */ - #ifndef CONFIG_DISABLE_ES2015_BUILTIN /** * The Array.prototype object's 'find' routine @@ -2416,42 +2003,15 @@ ecma_builtin_array_prototype_object_reduce_right (ecma_value_t this_arg, /**< th * Returned value must be freed with ecma_free_value. */ static ecma_value_t -ecma_builtin_array_prototype_object_find (ecma_value_t this_arg, /**< this argument */ - ecma_value_t predicate, /**< callback function */ - ecma_value_t predicate_this_arg) /**< this argument for +ecma_builtin_array_prototype_object_find (ecma_value_t predicate, /**< callback function */ + ecma_value_t predicate_this_arg, /**< this argument for * invoke predicate */ + ecma_object_t *obj_p, /**< array object */ + uint32_t len) /**< array object's length */ { - /* 1. */ - ecma_value_t obj_this = ecma_op_to_object (this_arg); - - /* 2. */ - if (ECMA_IS_VALUE_ERROR (obj_this)) - { - return obj_this; - } - - ecma_object_t *obj_p = ecma_get_object_from_value (obj_this); - - /* 3 - 4. */ - ecma_value_t len_value = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_LENGTH); - - if (ECMA_IS_VALUE_ERROR (len_value)) - { - ecma_free_value (obj_this); - return len_value; - } - - ecma_value_t ret_value = ECMA_VALUE_EMPTY; - - ECMA_OP_TO_NUMBER_TRY_CATCH (len_number, len_value, ret_value); - - uint32_t len = ecma_number_to_uint32 (len_number); - /* 5. */ if (!ecma_op_is_callable (predicate)) { - ecma_free_value (len_value); - ecma_free_value (obj_this); return ecma_raise_type_error (ECMA_ERR_MSG ("Callback function is not callable.")); } @@ -2459,6 +2019,8 @@ ecma_builtin_array_prototype_object_find (ecma_value_t this_arg, /**< this argum JERRY_ASSERT (ecma_is_value_object (predicate)); ecma_object_t *func_object_p = ecma_get_object_from_value (predicate); + ecma_value_t ret_value = ECMA_VALUE_EMPTY; + /* 7 - 8. */ for (uint32_t index = 0; index < len && ecma_is_value_empty (ret_value); index++) { @@ -2473,7 +2035,7 @@ ecma_builtin_array_prototype_object_find (ecma_value_t this_arg, /**< this argum /* 8.d - 8.e */ uint32_t current_index = ecma_make_uint32_value (index); - ecma_value_t call_args[] = { get_value, current_index, obj_this }; + ecma_value_t call_args[] = { get_value, current_index, ecma_make_object_value (obj_p) }; ECMA_TRY_CATCH (call_value, ecma_op_function_call (func_object_p, predicate_this_arg, call_args, 3), ret_value); @@ -2497,19 +2059,21 @@ ecma_builtin_array_prototype_object_find (ecma_value_t this_arg, /**< this argum ret_value = ECMA_VALUE_UNDEFINED; } - ECMA_OP_TO_NUMBER_FINALIZE (len_number); - ecma_free_value (len_value); - ecma_free_value (obj_this); - return ret_value; } /* ecma_builtin_array_prototype_object_find */ #endif /* !CONFIG_DISABLE_ES2015_BUILTIN */ #ifndef CONFIG_DISABLE_ES2015_ITERATOR_BUILTIN /** - * Helper function for Array.prototype object's {'keys', 'values', 'entries'} + * Helper function for Array.prototype object's {'keys', 'values', 'entries', '@@iterator'} * routines common parts. * + * See also: + * ECMA-262 v6, 22.1.3.4 + * ECMA-262 v6, 22.1.3.13 + * ECMA-262 v6, 22.1.3.29 + * ECMA-262 v6, 22.1.3.30 + * * Note: * Returned value must be freed with ecma_free_value. * @@ -2517,103 +2081,252 @@ ecma_builtin_array_prototype_object_find (ecma_value_t this_arg, /**< this argum * error - otherwise */ static ecma_value_t -ecma_builtin_array_iterators_helper (ecma_value_t this_arg, /**< this argument */ +ecma_builtin_array_iterators_helper (ecma_object_t *obj_p, /**< array object */ uint8_t type) /**< any combination of * ecma_array_iterator_type_t bits */ { - /* 1. */ + ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_ARRAY_ITERATOR_PROTOTYPE); + + return ecma_op_create_iterator_object (ecma_make_object_value (obj_p), + prototype_obj_p, + ECMA_PSEUDO_ARRAY_ITERATOR, + type); +} /* ecma_builtin_array_iterators_helper */ +#endif /* !CONFIG_DISABLE_ES2015_ITERATOR_BUILTIN */ + +/** + * Dispatcher of the built-in's routines + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +ecma_value_t +ecma_builtin_array_prototype_dispatch_routine (uint16_t builtin_routine_id, /**< built-in wide routine + * identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list_p[], /**< list of arguments + * passed to routine */ + ecma_length_t arguments_number) /**< length of arguments' list */ +{ ecma_value_t obj_this = ecma_op_to_object (this_arg); if (ECMA_IS_VALUE_ERROR (obj_this)) { - /* 2. */ return obj_this; } - ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_ARRAY_ITERATOR_PROTOTYPE); + ecma_object_t *obj_p = ecma_get_object_from_value (obj_this); - /* 3. */ - ecma_value_t ret_value = ecma_op_create_iterator_object (obj_this, - prototype_obj_p, - ECMA_PSEUDO_ARRAY_ITERATOR, - type); - ecma_free_value (obj_this); + if (JERRY_UNLIKELY (builtin_routine_id <= ECMA_ARRAY_PROTOTYPE_CONCAT)) + { + ecma_value_t ret_value; + + if (builtin_routine_id == ECMA_ARRAY_PROTOTYPE_TO_STRING) + { + ret_value = ecma_builtin_array_prototype_object_to_string (this_arg, obj_p); + } + else + { + JERRY_ASSERT (builtin_routine_id == ECMA_ARRAY_PROTOTYPE_CONCAT); + ret_value = ecma_builtin_array_prototype_object_concat (arguments_list_p, + arguments_number, + obj_p); + } + + ecma_deref_object (obj_p); + return ret_value; + } + +#ifndef CONFIG_DISABLE_ES2015_ITERATOR_BUILTIN + if (JERRY_UNLIKELY (builtin_routine_id >= ECMA_ARRAY_PROTOTYPE_ENTRIES + && builtin_routine_id <= ECMA_ARRAY_PROTOTYPE_SYMBOL_ITERATOR)) + { + ecma_value_t ret_value; + + if (builtin_routine_id == ECMA_ARRAY_PROTOTYPE_ENTRIES) + { + ret_value = ecma_builtin_array_iterators_helper (obj_p, ECMA_ARRAY_ITERATOR_KEYS_VALUES); + } + else if (builtin_routine_id == ECMA_ARRAY_PROTOTYPE_KEYS) + { + ret_value = ecma_builtin_array_iterators_helper (obj_p, ECMA_ARRAY_ITERATOR_KEYS); + } + else + { + JERRY_ASSERT (builtin_routine_id == ECMA_ARRAY_PROTOTYPE_VALUES + || builtin_routine_id == ECMA_ARRAY_PROTOTYPE_SYMBOL_ITERATOR); + + ret_value = ecma_builtin_array_iterators_helper (obj_p, ECMA_ARRAY_ITERATOR_VALUES); + } + + ecma_deref_object (obj_p); + return ret_value; + } +#endif /* !CONFIG_DISABLE_ES2015_ITERATOR_BUILTIN */ + + ecma_value_t len_value = ecma_op_object_get_by_magic_id (obj_p, LIT_MAGIC_STRING_LENGTH); + + if (ECMA_IS_VALUE_ERROR (len_value)) + { + ecma_deref_object (obj_p); + return len_value; + } + + ecma_number_t length_number; + ecma_value_t ret_value = ecma_get_number (len_value, &length_number); + + if (!ecma_is_value_empty (ret_value)) + { + ecma_free_value (len_value); + ecma_deref_object (obj_p); + return ret_value; + } + + uint32_t length = ecma_number_to_uint32 (length_number); + + ecma_value_t routine_arg_1 = arguments_list_p[0]; + ecma_value_t routine_arg_2 = arguments_list_p[1]; + + switch (builtin_routine_id) + { + case ECMA_ARRAY_PROTOTYPE_TO_LOCALE_STRING: + { + ret_value = ecma_builtin_array_prototype_object_to_locale_string (obj_p, length); + break; + } + case ECMA_ARRAY_PROTOTYPE_JOIN: + { + ret_value = ecma_builtin_array_prototype_join (routine_arg_1, obj_p, length); + break; + } + case ECMA_ARRAY_PROTOTYPE_POP: + { + ret_value = ecma_builtin_array_prototype_object_pop (obj_p, length); + break; + } + case ECMA_ARRAY_PROTOTYPE_PUSH: + { + ret_value = ecma_builtin_array_prototype_object_push (arguments_list_p, + arguments_number, + obj_p, + length); + break; + } + case ECMA_ARRAY_PROTOTYPE_REVERSE: + { + ret_value = ecma_builtin_array_prototype_object_reverse (this_arg, obj_p, length); + break; + } + case ECMA_ARRAY_PROTOTYPE_SHIFT: + { + ret_value = ecma_builtin_array_prototype_object_shift (obj_p, length); + break; + } + case ECMA_ARRAY_PROTOTYPE_SLICE: + { + ret_value = ecma_builtin_array_prototype_object_slice (routine_arg_1, + routine_arg_2, + obj_p, + length); + break; + } + case ECMA_ARRAY_PROTOTYPE_SORT: + { + ret_value = ecma_builtin_array_prototype_object_sort (this_arg, + routine_arg_1, + obj_p, + length); + break; + } + case ECMA_ARRAY_PROTOTYPE_SPLICE: + { + ret_value = ecma_builtin_array_prototype_object_splice (arguments_list_p, + arguments_number, + obj_p, + length); + break; + } + case ECMA_ARRAY_PROTOTYPE_UNSHIFT: + { + ret_value = ecma_builtin_array_prototype_object_unshift (arguments_list_p, + arguments_number, + obj_p, + length); + break; + } + case ECMA_ARRAY_PROTOTYPE_INDEX_OF: + { + ret_value = ecma_builtin_array_prototype_object_index_of (routine_arg_1, + routine_arg_2, + obj_p, + length); + break; + } + case ECMA_ARRAY_PROTOTYPE_LAST_INDEX_OF: + { + ret_value = ecma_builtin_array_prototype_object_last_index_of (arguments_list_p, + arguments_number, + obj_p, + length); + break; + } + case ECMA_ARRAY_PROTOTYPE_EVERY: + case ECMA_ARRAY_PROTOTYPE_SOME: + case ECMA_ARRAY_PROTOTYPE_FOR_EACH: + { + ret_value = ecma_builtin_array_apply (routine_arg_1, + routine_arg_2, + (array_routine_mode) builtin_routine_id - ECMA_ARRAY_PROTOTYPE_EVERY, + obj_p, + length); + break; + } + case ECMA_ARRAY_PROTOTYPE_MAP: + { + ret_value = ecma_builtin_array_prototype_object_map (routine_arg_1, + routine_arg_2, + obj_p, + length); + break; + } + case ECMA_ARRAY_PROTOTYPE_REDUCE: + case ECMA_ARRAY_PROTOTYPE_REDUCE_RIGHT: + { + ret_value = ecma_builtin_array_reduce_from (routine_arg_1, + routine_arg_2, + arguments_number, + builtin_routine_id == ECMA_ARRAY_PROTOTYPE_REDUCE, + obj_p, + length); + break; + } +#ifndef CONFIG_DISABLE_ES2015_BUILTIN + case ECMA_ARRAY_PROTOTYPE_FIND: + { + ret_value = ecma_builtin_array_prototype_object_find (routine_arg_1, + routine_arg_2, + obj_p, + length); + break; + } +#endif /* !CONFIG_DISABLE_ES2015_BUILTIN */ + default: + { + JERRY_ASSERT (builtin_routine_id == ECMA_ARRAY_PROTOTYPE_FILTER); + + ret_value = ecma_builtin_array_prototype_object_filter (routine_arg_1, + routine_arg_2, + obj_p, + length); + break; + } + } + + ecma_free_value (len_value); + ecma_deref_object (obj_p); return ret_value; -} /* ecma_builtin_array_iterators_helper */ - -/** - * The Array.prototype object's 'entries' routine - * - * See also: - * ECMA-262 v6, 22.1.3.4 - * - * Note: - * Returned value must be freed with ecma_free_value. - * - * @return iterator result object, if success - * error - otherwise - */ -static ecma_value_t -ecma_builtin_array_prototype_entries (ecma_value_t this_arg) /**< this argument */ -{ - return ecma_builtin_array_iterators_helper (this_arg, ECMA_ARRAY_ITERATOR_KEYS_VALUES); -} /* ecma_builtin_array_prototype_entries */ - -/** - * The Array.prototype object's 'values' routine - * - * See also: - * ECMA-262 v6, 22.1.3.29. - * - * Note: - * Returned value must be freed with ecma_free_value. - * - * @return iterator result object, if success - * error - otherwise - */ -static ecma_value_t -ecma_builtin_array_prototype_values (ecma_value_t this_arg) /**< this argument */ -{ - return ecma_builtin_array_iterators_helper (this_arg, ECMA_ARRAY_ITERATOR_VALUES); -} /* ecma_builtin_array_prototype_values */ - -/** - * The Array.prototype object's '@@iterator' routine - * - * See also: - * ECMA-262 v6, 22.1.3.30. - * - * Note: - * Returned value must be freed with ecma_free_value. - * - * @return iterator result object, if success - * error - otherwise - */ -static ecma_value_t -ecma_builtin_array_prototype_symbol_iterator (ecma_value_t this_arg) /**< this argument */ -{ - return ecma_builtin_array_prototype_values (this_arg); -} /* ecma_builtin_array_prototype_symbol_iterator */ - -/** - * The Array.prototype object's 'keys' routine - * - * See also: - * ECMA-262 v6, 22.1.3.13 - * - * Note: - * Returned value must be freed with ecma_free_value. - * - * @return iterator result object, if success - * error - otherwise - */ -static ecma_value_t -ecma_builtin_array_prototype_keys (ecma_value_t this_arg) /**< this argument */ -{ - return ecma_builtin_array_iterators_helper (this_arg, ECMA_ARRAY_ITERATOR_KEYS); -} /* ecma_builtin_array_prototype_keys */ -#endif /* !CONFIG_DISABLE_ES2015_ITERATOR_BUILTIN */ +} /* ecma_builtin_array_prototype_dispatch_routine */ /** * @} diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.inc.h index b0c8ad95b..eb3af8800 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.inc.h @@ -39,35 +39,37 @@ NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH, /* Routine properties: * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ -ROUTINE (LIT_MAGIC_STRING_TO_STRING_UL, ecma_builtin_array_prototype_object_to_string, 0, 0) -ROUTINE (LIT_MAGIC_STRING_TO_LOCALE_STRING_UL, ecma_builtin_array_prototype_object_to_locale_string, 0, 0) -ROUTINE (LIT_MAGIC_STRING_CONCAT, ecma_builtin_array_prototype_object_concat, NON_FIXED, 1) -ROUTINE (LIT_MAGIC_STRING_JOIN, ecma_builtin_array_prototype_join, 1, 1) -ROUTINE (LIT_MAGIC_STRING_POP, ecma_builtin_array_prototype_object_pop, 0, 0) -ROUTINE (LIT_MAGIC_STRING_PUSH, ecma_builtin_array_prototype_object_push, NON_FIXED, 1) -ROUTINE (LIT_MAGIC_STRING_REVERSE, ecma_builtin_array_prototype_object_reverse, 0, 0) -ROUTINE (LIT_MAGIC_STRING_SHIFT, ecma_builtin_array_prototype_object_shift, 0, 0) -ROUTINE (LIT_MAGIC_STRING_SLICE, ecma_builtin_array_prototype_object_slice, 2, 2) -ROUTINE (LIT_MAGIC_STRING_SORT, ecma_builtin_array_prototype_object_sort, 1, 1) -ROUTINE (LIT_MAGIC_STRING_SPLICE, ecma_builtin_array_prototype_object_splice, NON_FIXED, 2) -ROUTINE (LIT_MAGIC_STRING_UNSHIFT, ecma_builtin_array_prototype_object_unshift, NON_FIXED, 1) -ROUTINE (LIT_MAGIC_STRING_INDEX_OF_UL, ecma_builtin_array_prototype_object_index_of, 2, 1) -ROUTINE (LIT_MAGIC_STRING_LAST_INDEX_OF_UL, ecma_builtin_array_prototype_object_last_index_of, NON_FIXED, 1) -ROUTINE (LIT_MAGIC_STRING_EVERY, ecma_builtin_array_prototype_object_every, 2, 1) -ROUTINE (LIT_MAGIC_STRING_SOME, ecma_builtin_array_prototype_object_some, 2, 1) -ROUTINE (LIT_MAGIC_STRING_FOR_EACH_UL, ecma_builtin_array_prototype_object_for_each, 2, 1) -ROUTINE (LIT_MAGIC_STRING_MAP, ecma_builtin_array_prototype_object_map, 2, 1) -ROUTINE (LIT_MAGIC_STRING_FILTER, ecma_builtin_array_prototype_object_filter, 2, 1) -ROUTINE (LIT_MAGIC_STRING_REDUCE, ecma_builtin_array_prototype_object_reduce, NON_FIXED, 1) -ROUTINE (LIT_MAGIC_STRING_REDUCE_RIGHT_UL, ecma_builtin_array_prototype_object_reduce_right, NON_FIXED, 1) +ROUTINE (LIT_MAGIC_STRING_TO_STRING_UL, ECMA_ARRAY_PROTOTYPE_TO_STRING, 0, 0) +ROUTINE (LIT_MAGIC_STRING_TO_LOCALE_STRING_UL, ECMA_ARRAY_PROTOTYPE_TO_LOCALE_STRING, 0, 0) +ROUTINE (LIT_MAGIC_STRING_CONCAT, ECMA_ARRAY_PROTOTYPE_CONCAT, NON_FIXED, 1) +ROUTINE (LIT_MAGIC_STRING_JOIN, ECMA_ARRAY_PROTOTYPE_JOIN, 1, 1) +ROUTINE (LIT_MAGIC_STRING_POP, ECMA_ARRAY_PROTOTYPE_POP, 0, 0) +ROUTINE (LIT_MAGIC_STRING_PUSH, ECMA_ARRAY_PROTOTYPE_PUSH, NON_FIXED, 1) +ROUTINE (LIT_MAGIC_STRING_REVERSE, ECMA_ARRAY_PROTOTYPE_REVERSE, 0, 0) +ROUTINE (LIT_MAGIC_STRING_SHIFT, ECMA_ARRAY_PROTOTYPE_SHIFT, 0, 0) +ROUTINE (LIT_MAGIC_STRING_SLICE, ECMA_ARRAY_PROTOTYPE_SLICE, 2, 2) +ROUTINE (LIT_MAGIC_STRING_SORT, ECMA_ARRAY_PROTOTYPE_SORT, 1, 1) +ROUTINE (LIT_MAGIC_STRING_SPLICE, ECMA_ARRAY_PROTOTYPE_SPLICE, NON_FIXED, 2) +ROUTINE (LIT_MAGIC_STRING_UNSHIFT, ECMA_ARRAY_PROTOTYPE_UNSHIFT, NON_FIXED, 1) +ROUTINE (LIT_MAGIC_STRING_INDEX_OF_UL, ECMA_ARRAY_PROTOTYPE_INDEX_OF, 2, 1) +ROUTINE (LIT_MAGIC_STRING_LAST_INDEX_OF_UL, ECMA_ARRAY_PROTOTYPE_LAST_INDEX_OF, NON_FIXED, 1) +/* Note these 3 routines must be in this order */ +ROUTINE (LIT_MAGIC_STRING_EVERY, ECMA_ARRAY_PROTOTYPE_EVERY, 2, 1) +ROUTINE (LIT_MAGIC_STRING_SOME, ECMA_ARRAY_PROTOTYPE_SOME, 2, 1) +ROUTINE (LIT_MAGIC_STRING_FOR_EACH_UL, ECMA_ARRAY_PROTOTYPE_FOR_EACH, 2, 1) +ROUTINE (LIT_MAGIC_STRING_MAP, ECMA_ARRAY_PROTOTYPE_MAP, 2, 1) +ROUTINE (LIT_MAGIC_STRING_FILTER, ECMA_ARRAY_PROTOTYPE_FILTER, 2, 1) +/* Note these 2 routines must be in this order */ +ROUTINE (LIT_MAGIC_STRING_REDUCE, ECMA_ARRAY_PROTOTYPE_REDUCE, NON_FIXED, 1) +ROUTINE (LIT_MAGIC_STRING_REDUCE_RIGHT_UL, ECMA_ARRAY_PROTOTYPE_REDUCE_RIGHT, NON_FIXED, 1) #ifndef CONFIG_DISABLE_ES2015_BUILTIN -ROUTINE (LIT_MAGIC_STRING_FIND, ecma_builtin_array_prototype_object_find, 2, 1) +ROUTINE (LIT_MAGIC_STRING_FIND, ECMA_ARRAY_PROTOTYPE_FIND, 2, 1) #endif /* !CONFIG_DISABLE_ES2015_BUILTIN */ #ifndef CONFIG_DISABLE_ES2015_ITERATOR_BUILTIN -ROUTINE (LIT_MAGIC_STRING_ENTRIES, ecma_builtin_array_prototype_entries, 0, 0) -ROUTINE (LIT_MAGIC_STRING_VALUES, ecma_builtin_array_prototype_values, 0, 0) -ROUTINE (LIT_MAGIC_STRING_KEYS, ecma_builtin_array_prototype_keys, 0, 0) -ROUTINE (LIT_GLOBAL_SYMBOL_ITERATOR, ecma_builtin_array_prototype_symbol_iterator, 0, 0) +ROUTINE (LIT_MAGIC_STRING_ENTRIES, ECMA_ARRAY_PROTOTYPE_ENTRIES, 0, 0) +ROUTINE (LIT_MAGIC_STRING_VALUES, ECMA_ARRAY_PROTOTYPE_VALUES, 0, 0) +ROUTINE (LIT_MAGIC_STRING_KEYS, ECMA_ARRAY_PROTOTYPE_KEYS, 0, 0) +ROUTINE (LIT_GLOBAL_SYMBOL_ITERATOR, ECMA_ARRAY_PROTOTYPE_SYMBOL_ITERATOR, 0, 0) #endif /* !CONFIG_DISABLE_ES2015_ITERATOR_BUILTIN */ #endif /* !CONFIG_DISABLE_ARRAY_BUILTIN */