From b6eea7555ec814838e22fc1581bb974165a1a3a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20B=C3=A1tyai?= Date: Thu, 21 May 2015 11:01:58 +0200 Subject: [PATCH] Implemented Array.prototype.some() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JerryScript-DCO-1.0-Signed-off-by: Dániel Bátyai dbatyai.u-szeged@partner.samsung.com --- .../ecma-builtin-array-prototype.cpp | 101 ++++++++++++++++++ .../ecma-builtin-array-prototype.inc.h | 1 + tests/jerry/array_prototype_some.js | 62 +++++++++++ 3 files changed, 164 insertions(+) create mode 100644 tests/jerry/array_prototype_some.js 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 0943bd2f3a..0a800804ec 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.cpp +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.cpp @@ -702,6 +702,107 @@ ecma_builtin_array_prototype_object_unshift (ecma_value_t this_arg, /**< this ar return ret_value; } /* ecma_builtin_array_prototype_object_unshift */ +/** + * The Array.prototype object's 'some' routine + * + * See also: + * ECMA-262 v5, 15.4.4.17 + * + * @return completion value + * Returned value must be freed with ecma_free_completion_value. + */ +static ecma_completion_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 */ +{ + ecma_completion_value_t ret_value = 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_value_t current_index; + ecma_number_t *num_p = ecma_alloc_number (); + ecma_object_t *func_object_p; + + /* We already checked that arg1 is callable, so it will always coerce to an object. */ + 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); + + /* 7. */ + for (uint32_t index = 0; index < len && ecma_is_completion_value_empty (ret_value); index++) + { + /* 7.a */ + ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (index); + + /* 7.c */ + if (ecma_op_object_get_property (obj_p, index_str_p) != NULL) + { + /* 7.c.i */ + ECMA_TRY_CATCH (get_value, ecma_op_object_get (obj_p, index_str_p), ret_value); + + *num_p = ecma_uint32_to_number (index); + current_index = ecma_make_number_value (num_p); + + 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, ecma_op_to_boolean always returns a simple value, so no need to free. */ + if (ecma_is_value_true (ecma_op_to_boolean (call_value))) + { + ret_value = ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_TRUE); + } + + ECMA_FINALIZE (call_value); + ECMA_FINALIZE (get_value); + } + + ecma_deref_ecma_string (index_str_p); + } + + ecma_free_completion_value (to_object_comp); + ecma_dealloc_number (num_p); + + if (ecma_is_completion_value_empty (ret_value)) + { + /* 8. */ + ret_value = ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_FALSE); + } + } + + ECMA_OP_TO_NUMBER_FINALIZE (len_number); + ECMA_FINALIZE (len_value); + ecma_deref_ecma_string (magic_string_length_p); + ECMA_FINALIZE (obj_this); + + return ret_value; +} /* ecma_builtin_array_prototype_object_some */ + /** * @} * @} 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 2cb4a4371b..0bb0a3592d 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 @@ -63,6 +63,7 @@ ROUTINE (ECMA_MAGIC_STRING_TO_STRING_UL, ecma_builtin_array_prototype_object_to_ ROUTINE (ECMA_MAGIC_STRING_POP, ecma_builtin_array_prototype_object_pop, 0, 0) ROUTINE (ECMA_MAGIC_STRING_PUSH, ecma_builtin_array_prototype_object_push, NON_FIXED, 1) ROUTINE (ECMA_MAGIC_STRING_INDEX_OF_UL, ecma_builtin_array_prototype_object_index_of, 2, 1) +ROUTINE (ECMA_MAGIC_STRING_SOME, ecma_builtin_array_prototype_object_some, 2, 1) ROUTINE (ECMA_MAGIC_STRING_SHIFT, ecma_builtin_array_prototype_object_shift, 0, 0) ROUTINE (ECMA_MAGIC_STRING_UNSHIFT, ecma_builtin_array_prototype_object_unshift, NON_FIXED, 1) diff --git a/tests/jerry/array_prototype_some.js b/tests/jerry/array_prototype_some.js new file mode 100644 index 0000000000..4e61fd2c78 --- /dev/null +++ b/tests/jerry/array_prototype_some.js @@ -0,0 +1,62 @@ +// Copyright 2015 Samsung Electronics Co., Ltd. +// Copyright 2015 University of Szeged. +// +// 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 array = ["foo", [], Infinity, 4]; + +function f(arg1, arg2, arg3) { + assert(arg1 === array[arg2]); + assert(arg3 === array); + return false; +} + +assert(array.some(f) === false); + +function g(arg1, arg2, arg3) { + if (arg1 === 1) { + return true; + } else { + return false; + } +} + +var arr1 = [2, 2, 2, 2, 2, 2]; +assert(arr1.some(g) === false); + +var arr2 = [2, 2, 2, 2, 2, 1]; +assert(arr2.some(g) === true); + +// Checking behavior when unable to get length +var obj = { some : Array.prototype.some }; +Object.defineProperty(obj, 'length', { 'get' : function () {throw new ReferenceError ("foo"); } }); + +try { + obj.some(f); + assert(false); +} catch (e) { + assert(e.message === "foo"); + assert(e instanceof ReferenceError); +} + +// Checking behavior when unable to get element +var obj = { some : Array.prototype.some, length : 1}; +Object.defineProperty(obj, '0', { 'get' : function () {throw new ReferenceError ("foo"); } }); + +try { + obj.some(f); + assert(false); +} catch (e) { + assert(e.message === "foo"); + assert(e instanceof ReferenceError); +}