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 eb52ee9cb..0ed245b65 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 @@ -354,6 +354,166 @@ ecma_builtin_typedarray_prototype_map (ecma_value_t this_arg, /**< this argument return ret_value; } /* ecma_builtin_typedarray_prototype_map */ +/** + * Reduce and reduceRight routines share a similar structure. + * And we use 'is_right' to distinguish between them. + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_reduce_with_direction (ecma_value_t this_arg, /**< this argument */ + ecma_value_t cb_func_val, /**< callback function */ + ecma_value_t initial_val, /**< initial value */ + bool is_right) /**< choose order, true is reduceRight */ +{ + if (!ecma_is_typedarray (this_arg)) + { + return ecma_raise_type_error (ECMA_ERR_MSG ("Argument 'this' is not a TypedArray.")); + } + + if (!ecma_op_is_callable (cb_func_val)) + { + return ecma_raise_type_error (ECMA_ERR_MSG ("Callback function is not callable.")); + } + + ecma_object_t *obj_p = ecma_get_object_from_value (this_arg); + uint32_t len = ecma_typedarray_get_length (obj_p); + + if (len == 0) + { + if (ecma_is_value_undefined (initial_val)) + { + return ecma_raise_type_error (ECMA_ERR_MSG ("Initial value cannot be undefined.")); + } + + return ecma_copy_value (initial_val); + } + + JERRY_ASSERT (len > 0); + + ecma_value_t accumulator = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); + uint32_t index = is_right ? (len - 1) : 0; + + if (ecma_is_value_undefined (initial_val)) + { + accumulator = ecma_op_typedarray_get_index_prop (obj_p, index); + + JERRY_ASSERT (ecma_is_value_number (accumulator)); + + if (is_right) + { + if (index == 0) + { + return accumulator; + } + + index--; + } + else + { + index++; + + if (index == len) + { + return accumulator; + } + } + } + else + { + accumulator = ecma_copy_value (initial_val); + } + + ecma_object_t *func_object_p = ecma_get_object_from_value (cb_func_val); + + while (true) + { + ecma_value_t current_index = ecma_make_uint32_value (index); + ecma_value_t get_value = ecma_op_typedarray_get_index_prop (obj_p, index); + ecma_value_t call_args[] = { accumulator, get_value, current_index, this_arg }; + + JERRY_ASSERT (ecma_is_value_number (get_value)); + + ecma_value_t call_value = ecma_op_function_call (func_object_p, + ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED), + call_args, + 4); + + ecma_fast_free_value (accumulator); + ecma_fast_free_value (get_value); + ecma_fast_free_value (current_index); + + if (ECMA_IS_VALUE_ERROR (call_value)) + { + return call_value; + } + + accumulator = call_value; + + if (is_right) + { + if (index == 0) + { + break; + } + + index--; + } + else + { + index++; + + if (index == len) + { + break; + } + } + } + + return accumulator; +} /* ecma_builtin_typedarray_prototype_reduce_with_direction */ + +/** + * The %TypedArray%.prototype object's 'reduce' routine + * + * See also: + * ES2015, 22.2.3.19 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_reduce (ecma_value_t this_arg, /**< this argument */ + ecma_value_t cb_func_val, /**< callback function */ + ecma_value_t initial_val) /**< initial value */ +{ + return ecma_builtin_typedarray_prototype_reduce_with_direction (this_arg, + cb_func_val, + initial_val, + false); +} /* ecma_builtin_typedarray_prototype_reduce */ + +/** + * The %TypedArray%.prototype object's 'reduceRight' routine + * + * See also: + * ES2015, 22.2.3.20 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_reduce_right (ecma_value_t this_arg, /**< this argument */ + ecma_value_t cb_func_val, /**< callback function */ + ecma_value_t initial_val) /**< initial value */ +{ + return ecma_builtin_typedarray_prototype_reduce_with_direction (this_arg, + cb_func_val, + initial_val, + true); +} /* ecma_builtin_typedarray_prototype_reduce_right */ + /** * @} * @} diff --git a/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype.inc.h b/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype.inc.h index 4f4cd2e2a..67542709e 100644 --- a/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype.inc.h +++ b/jerry-core/ecma/builtin-objects/typedarray/ecma-builtin-typedarray-prototype.inc.h @@ -60,6 +60,8 @@ ROUTINE (LIT_MAGIC_STRING_EVERY, ecma_builtin_typedarray_prototype_every, 2, 1) ROUTINE (LIT_MAGIC_STRING_SOME, ecma_builtin_typedarray_prototype_some, 2, 1) ROUTINE (LIT_MAGIC_STRING_FOR_EACH_UL, ecma_builtin_typedarray_prototype_for_each, 2, 1) ROUTINE (LIT_MAGIC_STRING_MAP, ecma_builtin_typedarray_prototype_map, 2, 1) +ROUTINE (LIT_MAGIC_STRING_REDUCE, ecma_builtin_typedarray_prototype_reduce, 2, 1) +ROUTINE (LIT_MAGIC_STRING_REDUCE_RIGHT_UL, ecma_builtin_typedarray_prototype_reduce_right, 2, 1) #undef SIMPLE_VALUE #undef NUMBER_VALUE diff --git a/tests/jerry-test-suite/es2015/22/22.02/22.02.03/22.02.03-015.js b/tests/jerry-test-suite/es2015/22/22.02/22.02.03/22.02.03-015.js new file mode 100644 index 000000000..2ea42474a --- /dev/null +++ b/tests/jerry-test-suite/es2015/22/22.02/22.02.03/22.02.03-015.js @@ -0,0 +1,20 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var total = new Float32Array([-1.5, 0, 1.5, 2]).reduce(function(a, b, c) { + return a + b + c; +}, 10); + +assert(total === 18); // 10 + (-1.5) + 0 + 0 + 1 + 1.5 + 2 + 2 + 3 diff --git a/tests/jerry-test-suite/es2015/22/22.02/22.02.03/22.02.03-016.js b/tests/jerry-test-suite/es2015/22/22.02/22.02.03/22.02.03-016.js new file mode 100644 index 000000000..4e5950c98 --- /dev/null +++ b/tests/jerry-test-suite/es2015/22/22.02/22.02.03/22.02.03-016.js @@ -0,0 +1,20 @@ +/* Copyright JS Foundation and other contributors, http://js.foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var total = new Float32Array([-1.5, 0, 1.5, 2]).reduceRight(function(a, b) { + return a - b; +}); + +assert (total === 2) // 2 - 1.5 - 0 - (-1.5)