From d6e4e1985284c09f7222e0292bd81b3dac1bc7d2 Mon Sep 17 00:00:00 2001 From: Laszlo Vidacs Date: Fri, 22 May 2015 15:31:07 +0200 Subject: [PATCH] Implement Array.prototype.reduce() JerryScript-DCO-1.0-Signed-off-by: Laszlo Vidacs lvidacs.u-szeged@partner.samsung.com --- .../ecma-builtin-array-prototype.cpp | 137 ++++++++++++++++++ .../ecma-builtin-array-prototype.inc.h | 1 + 2 files changed, 138 insertions(+) diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.cpp b/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.cpp index c845c8541..c764d753e 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.cpp +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.cpp @@ -2452,6 +2452,143 @@ ecma_builtin_array_prototype_object_splice (ecma_value_t this_arg, /**< this arg return ret_value; } /* ecma_builtin_array_prototype_object_splice */ + +/** + * The Array.prototype object's 'reduce' routine + * + * See also: + * ECMA-262 v5, 15.4.4.21 + * + * @return completion value + * Returned value must be freed with ecma_free_completion_value. + */ +static ecma_completion_value_t +ecma_builtin_array_prototype_object_reduce (ecma_value_t this_arg, /**< this argument */ + ecma_value_t arg1, /**< callbackfn */ + ecma_value_t arg2) /**< initialValue */ +{ + ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); + ecma_completion_value_t accumulator = ecma_make_empty_completion_value (); + /* 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_string_t *magic_string_length_p = ecma_get_magic_string (ECMA_MAGIC_STRING_LENGTH); + + /* 2 */ + ECMA_TRY_CATCH (len_value, + ecma_op_object_get (obj_p, magic_string_length_p), + 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_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE)); + } + else + { + ecma_number_t *num_p = ecma_alloc_number (); + ecma_object_t *func_object_p; + ecma_value_t current_index; + + ecma_completion_value_t to_object_comp = ecma_op_to_object (arg1); + JERRY_ASSERT (ecma_is_completion_value_normal (to_object_comp)); + func_object_p = ecma_get_object_from_completion_value (to_object_comp); + + /* 5 */ + if (len_number == ECMA_NUMBER_ZERO && ecma_is_value_undefined (arg1)) + { + ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE)); + } + + /* 6 */ + uint32_t index = 0; + + /* 7a */ + if (!ecma_is_value_undefined (arg2)) + { + accumulator = ecma_copy_completion_value (arg2); + } + else + { + /* 8a */ + bool kPresent = false; + /* 8b */ + while (!kPresent && index < len && ecma_is_completion_value_empty (ret_value)) + { + /* 8b-i */ + ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (index); + + /* 8b-ii-iii */ + if ((kPresent = (ecma_op_object_get_property (obj_p, index_str_p) != NULL))) + { + ECMA_TRY_CATCH (current_value, ecma_op_object_get (obj_p, index_str_p), ret_value); + accumulator = ecma_copy_completion_value (current_value); + ECMA_FINALIZE (current_value); + } + /* 8b-iv */ + index++; + + ecma_deref_ecma_string (index_str_p); + } + /* 8c */ + if (!kPresent) + { + ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE)); + } + } + /* 9 */ + for (; index < len && ecma_is_completion_value_empty (ret_value); ++index) + { + /* 9a */ + ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (index); + /* 9b */ + if (ecma_op_object_get_property (obj_p, index_str_p) != NULL) + { + /* 9c-i */ + ECMA_TRY_CATCH (current_value, ecma_op_object_get (obj_p, index_str_p), ret_value); + /* 9c-ii */ + *num_p = ecma_uint32_to_number (index); + current_index = ecma_make_number_value (num_p); + ecma_value_t prev_value = ecma_get_completion_value_value (accumulator); + ecma_value_t call_args[] = {prev_value, current_value, current_index, obj_this}; + + ECMA_TRY_CATCH (call_value, + ecma_op_function_call (func_object_p, ECMA_SIMPLE_VALUE_UNDEFINED, call_args, 4), ret_value); + accumulator = ecma_copy_completion_value (call_value); + + ECMA_FINALIZE (call_value); + ECMA_FINALIZE (current_value); + } + ecma_deref_ecma_string (index_str_p); + /* 9d in for loop */ + } + + ecma_free_completion_value (to_object_comp); + ecma_dealloc_number (num_p); + } + + ECMA_OP_TO_NUMBER_FINALIZE (len_number); + ECMA_FINALIZE (len_value); + ecma_deref_ecma_string (magic_string_length_p); + ECMA_FINALIZE (obj_this); + + if (ecma_is_completion_value_empty (ret_value)) + { + ret_value = ecma_copy_completion_value (accumulator); + } + ecma_free_completion_value (accumulator); + + return ret_value; +} /* ecma_builtin_array_prototype_object_reduce */ + /** * @} * @} 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 93aa63421..1702e610f 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 @@ -76,6 +76,7 @@ ROUTINE (ECMA_MAGIC_STRING_SOME, ecma_builtin_array_prototype_object_some, 2, 1) ROUTINE (ECMA_MAGIC_STRING_SLICE, ecma_builtin_array_prototype_object_slice, 2, 2) ROUTINE (ECMA_MAGIC_STRING_SPLICE, ecma_builtin_array_prototype_object_splice, NON_FIXED, 2) ROUTINE (ECMA_MAGIC_STRING_FILTER, ecma_builtin_array_prototype_object_filter, 2, 1) +ROUTINE (ECMA_MAGIC_STRING_REDUCE, ecma_builtin_array_prototype_object_reduce, 2, 1) #undef OBJECT_ID #undef SIMPLE_VALUE