From f0578b2c2578446131ad42918840aaf20576425c Mon Sep 17 00:00:00 2001 From: Szilagyi Adam Date: Fri, 30 Aug 2019 14:01:30 +0200 Subject: [PATCH] Add indexOf and lastIndexOf function to typedArray (#2938) The algorithm's are based on ECMA-262 v6, 22.2.3.13, 22.2.3.16 Co-authored-by: Tibor Dusnoki tdusnoki@inf.u-szeged.hu JerryScript-DCO-1.0-Signed-off-by: Adam Szilagyi aszilagy@inf.u-szeged.hu --- .../ecma-builtin-array-prototype.c | 58 +-------- .../ecma-builtin-arraybuffer-prototype.c | 4 +- .../builtin-objects/ecma-builtin-helpers.c | 31 +++-- .../builtin-objects/ecma-builtin-helpers.h | 2 +- .../ecma-builtin-string-prototype.c | 5 +- .../ecma-builtin-typedarray-prototype.c | 118 +++++++++++++++++- .../ecma-builtin-typedarray-prototype.inc.h | 2 + jerry-core/lit/lit-magic-strings.inc.h | 6 +- .../es2015/typedarray-prototype-indexof.js | 104 +++++++++++++++ .../typedarray-prototype-lastindexof.js | 102 +++++++++++++++ 10 files changed, 360 insertions(+), 72 deletions(-) create mode 100644 tests/jerry/es2015/typedarray-prototype-indexof.js create mode 100644 tests/jerry/es2015/typedarray-prototype-lastindexof.js 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 aff483cdd..267e63c03 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.c @@ -750,7 +750,7 @@ ecma_builtin_array_prototype_object_slice (ecma_value_t arg1, /**< start */ return ECMA_VALUE_ERROR; } - start = ecma_builtin_helper_array_index_normalize (start_num, len); + start = ecma_builtin_helper_array_index_normalize (start_num, len, false); /* 7. */ if (ecma_is_value_undefined (arg2)) @@ -767,7 +767,7 @@ ecma_builtin_array_prototype_object_slice (ecma_value_t arg1, /**< start */ return ECMA_VALUE_ERROR; } - end = ecma_builtin_helper_array_index_normalize (end_num, len); + end = ecma_builtin_helper_array_index_normalize (end_num, len, false); } JERRY_ASSERT (start <= len && end <= len); @@ -1122,7 +1122,7 @@ ecma_builtin_array_prototype_object_splice (const ecma_value_t args[], /**< argu return ECMA_VALUE_ERROR; } - start = ecma_builtin_helper_array_index_normalize (start_num, len); + start = ecma_builtin_helper_array_index_normalize (start_num, len, false); /* * If there is only one argument, that will be the start argument, @@ -1434,7 +1434,7 @@ ecma_builtin_array_prototype_object_index_of (ecma_value_t arg1, /**< searchElem ecma_number_t found_index = ECMA_NUMBER_MINUS_ONE; - uint32_t from_idx = ecma_builtin_helper_array_index_normalize (arg_from_idx, len); + uint32_t from_idx = ecma_builtin_helper_array_index_normalize (arg_from_idx, len, false); /* 6. */ for (; from_idx < len && found_index < 0; from_idx++) @@ -1483,7 +1483,6 @@ ecma_builtin_array_prototype_object_last_index_of (const ecma_value_t args[], /* uint32_t from_idx = len - 1; - /* 5. */ if (args_number > 1) { ecma_number_t arg_from_idx; @@ -1492,54 +1491,7 @@ ecma_builtin_array_prototype_object_last_index_of (const ecma_value_t args[], /* return ECMA_VALUE_ERROR; } - if (!ecma_number_is_nan (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; - } - } - } - } - else - { - from_idx = 0; - } + from_idx = ecma_builtin_helper_array_index_normalize (arg_from_idx, len, true); } ecma_number_t num = ECMA_NUMBER_MINUS_ONE; diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer-prototype.c b/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer-prototype.c index 4e16a284b..e393912f4 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer-prototype.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-arraybuffer-prototype.c @@ -106,7 +106,7 @@ ecma_builtin_arraybuffer_prototype_object_slice (ecma_value_t this_arg, /**< thi arg1, ret_value); - start = ecma_builtin_helper_array_index_normalize (start_num, len); + start = ecma_builtin_helper_array_index_normalize (start_num, len, false); if (!ecma_is_value_undefined (arg2)) { @@ -114,7 +114,7 @@ ecma_builtin_arraybuffer_prototype_object_slice (ecma_value_t this_arg, /**< thi arg2, ret_value); - end = ecma_builtin_helper_array_index_normalize (end_num, len); + end = ecma_builtin_helper_array_index_normalize (end_num, len, false); ECMA_OP_TO_NUMBER_FINALIZE (end_num); } diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.c b/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.c index fbd0c036b..b22f36a59 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.c @@ -314,7 +314,7 @@ ecma_builtin_helper_object_get_properties (ecma_object_t *obj_p, /**< object */ * If the index is negative, it is used as the offset from the end of the array, * to compute normalized index. * If the index is greater than the length of the array, the normalized index will be the length of the array. - * + * If is_last_index_of is true, then we use the method in ECMA-262 v6, 22.2.3.16 to compute the normalized index. * See also: * ECMA-262 v5, 15.4.4.10 steps 5-6, 7 (part 2) and 8 * ECMA-262 v5, 15.4.4.12 steps 5-6 @@ -326,12 +326,15 @@ ecma_builtin_helper_object_get_properties (ecma_object_t *obj_p, /**< object */ * - The Array.prototype.splice routine. * - The Array.prototype.indexOf routine. * - The String.prototype.slice routine. + * - The TypedArray.prototype.indexOf routine. + * - The TypedArray.prototype.lastIndexOf routine * * @return uint32_t - the normalized value of the index */ uint32_t ecma_builtin_helper_array_index_normalize (ecma_number_t index, /**< index */ - uint32_t length) /**< array's length */ + uint32_t length, /**< array's length */ + bool is_last_index_of) /**< true - normalize for lastIndexOf method*/ { uint32_t norm_index; @@ -344,7 +347,14 @@ ecma_builtin_helper_array_index_normalize (ecma_number_t index, /**< index */ } else if (ecma_number_is_infinity (index)) { - norm_index = ecma_number_is_negative (index) ? 0 : length; + if (is_last_index_of) + { + norm_index = ecma_number_is_negative (index) ? (uint32_t) -1 : length - 1; + } + else + { + norm_index = ecma_number_is_negative (index) ? 0 : length; + } } else { @@ -352,20 +362,27 @@ ecma_builtin_helper_array_index_normalize (ecma_number_t index, /**< index */ { ecma_number_t index_neg = -index; - if (index_neg > length) + if (is_last_index_of) { - norm_index = 0; + norm_index = length - ecma_number_to_uint32 (index_neg); } else { - norm_index = length - ecma_number_to_uint32 (index_neg); + if (index_neg > length) + { + norm_index = 0; + } + else + { + norm_index = length - ecma_number_to_uint32 (index_neg); + } } } else { if (index > length) { - norm_index = length; + norm_index = is_last_index_of ? length - 1 : length; } else { diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.h b/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.h index f0a23447a..6f7ccb221 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-helpers.h @@ -48,7 +48,7 @@ ecma_builtin_helper_object_get_properties (ecma_object_t *obj_p, uint32_t opts); ecma_value_t ecma_builtin_helper_array_concat_value (ecma_object_t *obj_p, uint32_t *length_p, ecma_value_t value); uint32_t -ecma_builtin_helper_array_index_normalize (ecma_number_t index, uint32_t length); +ecma_builtin_helper_array_index_normalize (ecma_number_t index, uint32_t length, bool last_index_of); uint32_t ecma_builtin_helper_string_index_normalize (ecma_number_t index, uint32_t length, bool nan_to_zero); ecma_value_t diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.c b/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.c index eca64caf9..952b91ff8 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-string-prototype.c @@ -1275,7 +1275,7 @@ ecma_builtin_string_prototype_object_slice (ecma_string_t *get_string_val, /**< return ECMA_VALUE_ERROR; } - start = ecma_builtin_helper_array_index_normalize (start_num, len); + start = ecma_builtin_helper_array_index_normalize (start_num, len, false); /* 5. 7. */ if (ecma_is_value_undefined (arg2)) @@ -1291,10 +1291,9 @@ ecma_builtin_string_prototype_object_slice (ecma_string_t *get_string_val, /**< return ECMA_VALUE_ERROR; } - end = ecma_builtin_helper_array_index_normalize (end_num, len); + end = ecma_builtin_helper_array_index_normalize (end_num, len, false); } - JERRY_ASSERT (start <= len && end <= len); /* 8-9. */ 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 9a78460f2..b285d3a86 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 @@ -16,6 +16,7 @@ #include "ecma-builtin-helpers.h" #include "ecma-builtin-typedarray-helpers.h" #include "ecma-builtins.h" +#include "ecma-comparison.h" #include "ecma-exceptions.h" #include "ecma-globals.h" #include "ecma-helpers.h" @@ -1249,7 +1250,7 @@ ecma_builtin_typedarray_prototype_subarray (ecma_value_t this_arg, /**< this arg /* 7. relativeBegin */ ECMA_OP_TO_NUMBER_TRY_CATCH (relative_begin, begin, ret_value); - begin_index_uint32 = ecma_builtin_helper_array_index_normalize (relative_begin, src_length); + begin_index_uint32 = ecma_builtin_helper_array_index_normalize (relative_begin, src_length, false); if (ecma_is_value_undefined (end)) { @@ -1260,7 +1261,7 @@ ecma_builtin_typedarray_prototype_subarray (ecma_value_t this_arg, /**< this arg /* 10. relativeEnd */ ECMA_OP_TO_NUMBER_TRY_CATCH (relative_end, end, ret_value); - end_index_uint32 = ecma_builtin_helper_array_index_normalize (relative_end, src_length); + end_index_uint32 = ecma_builtin_helper_array_index_normalize (relative_end, src_length, false); ECMA_OP_TO_NUMBER_FINALIZE (relative_end); } @@ -1341,7 +1342,7 @@ ecma_builtin_typedarray_prototype_fill (ecma_value_t this_arg, /**< this argumen uint32_t begin_index_uint32 = 0, end_index_uint32 = 0; ECMA_OP_TO_NUMBER_TRY_CATCH (relative_begin, begin, ret_value); - begin_index_uint32 = ecma_builtin_helper_array_index_normalize (relative_begin, length); + begin_index_uint32 = ecma_builtin_helper_array_index_normalize (relative_begin, length, false); if (ecma_is_value_undefined (end)) { @@ -1351,7 +1352,7 @@ ecma_builtin_typedarray_prototype_fill (ecma_value_t this_arg, /**< this argumen { ECMA_OP_TO_NUMBER_TRY_CATCH (relative_end, end, ret_value); - end_index_uint32 = ecma_builtin_helper_array_index_normalize (relative_end, length); + end_index_uint32 = ecma_builtin_helper_array_index_normalize (relative_end, length, false); ECMA_OP_TO_NUMBER_FINALIZE (relative_end); } @@ -1687,6 +1688,115 @@ ecma_builtin_typedarray_prototype_find_index (ecma_value_t this_arg, /**< this a return ecma_builtin_typedarray_prototype_find_helper (this_arg, predicate, predicate_this_arg, false); } /* ecma_builtin_typedarray_prototype_find_index */ +/** + * The %TypedArray%.prototype object's 'indexOf' and 'lastIndexOf' routine helper + * + * See also: + * ECMA-262 v6, 22.2.3.13, 22.2.3.16 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_index_helper (ecma_value_t this_arg, /**< this argument */ + const ecma_value_t args[], /**< arguments list */ + ecma_length_t args_number, /**< number of arguments */ + bool is_last_index_of) /**< true - lastIndexOf routine + false - indexOf routine */ +{ + if (!ecma_is_typedarray (this_arg)) + { + return ecma_raise_type_error (ECMA_ERR_MSG ("Argument 'this' is not a TypedArray.")); + } + + ecma_object_t *typedarray_p = ecma_get_object_from_value (this_arg); + uint32_t length = ecma_typedarray_get_length (typedarray_p); + lit_magic_string_id_t class_id = ecma_object_get_class_name (typedarray_p); + lit_utf8_byte_t *typedarray_buffer_p = ecma_typedarray_get_buffer (typedarray_p); + uint8_t shift = ecma_typedarray_get_element_size_shift (typedarray_p); + uint8_t element_size = (uint8_t) (1 << shift); + uint32_t limit = length * element_size; + uint32_t from_index; + + if (args_number == 0 + || length == 0) + { + return ecma_make_integer_value (-1); + } + if (args_number == 1) + { + from_index = is_last_index_of ? length - 1 : 0; + } + else + { + ecma_number_t num_var; + + if (ECMA_IS_VALUE_ERROR (ecma_get_number (args[1], &num_var))) + { + return ECMA_VALUE_ERROR; + } + + from_index = ecma_builtin_helper_array_index_normalize (num_var, length, is_last_index_of); + } + + if (!ecma_is_value_number (args[0])) + { + return ecma_make_integer_value (-1); + } + + ecma_number_t search_num = ecma_get_number_from_value (args[0]); + + int32_t increment = is_last_index_of ? -element_size : element_size; + + for (int32_t position = (int32_t) from_index * element_size; + (is_last_index_of ? position >= 0 : (uint32_t) position < limit); + position += increment) + { + ecma_number_t element_num = ecma_get_typedarray_element (typedarray_buffer_p + position, class_id); + + if (search_num == element_num) + { + return ecma_make_number_value ((ecma_number_t) position / element_size); + } + } + + return ecma_make_integer_value (-1); +} /* ecma_builtin_typedarray_prototype_index_helper */ + +/** + * The %TypedArray%.prototype object's 'indexOf' routine + * + * See also: + * ECMA-262 v6, 22.2.3.13 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_index_of (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_typedarray_prototype_index_helper (this_arg, args, args_number, false); +} /* ecma_builtin_typedarray_prototype_index_of */ + +/** + * The %TypedArray%.prototype object's 'lastIndexOf' routine + * + * See also: + * ECMA-262 v6, 22.2.3.16 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_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 */ +{ + return ecma_builtin_typedarray_prototype_index_helper (this_arg, args, args_number, true); +} /* ecma_builtin_typedarray_prototype_last_index_of */ + /** * @} * @} 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 ef0360dae..909b14da2 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 @@ -70,6 +70,8 @@ ROUTINE (LIT_MAGIC_STRING_FILL, ecma_builtin_typedarray_prototype_fill, 3, 1) ROUTINE (LIT_MAGIC_STRING_SORT, ecma_builtin_typedarray_prototype_sort, 1, 1) ROUTINE (LIT_MAGIC_STRING_FIND, ecma_builtin_typedarray_prototype_find, 2, 1) ROUTINE (LIT_MAGIC_STRING_FIND_INDEX, ecma_builtin_typedarray_prototype_find_index, 2, 1) +ROUTINE (LIT_MAGIC_STRING_INDEX_OF_UL, ecma_builtin_typedarray_prototype_index_of, NON_FIXED, 1) +ROUTINE (LIT_MAGIC_STRING_LAST_INDEX_OF_UL, ecma_builtin_typedarray_prototype_last_index_of, NON_FIXED, 1) #if ENABLED (JERRY_ES2015_BUILTIN_ITERATOR) diff --git a/jerry-core/lit/lit-magic-strings.inc.h b/jerry-core/lit/lit-magic-strings.inc.h index fcead7c1f..1e492045d 100644 --- a/jerry-core/lit/lit-magic-strings.inc.h +++ b/jerry-core/lit/lit-magic-strings.inc.h @@ -385,7 +385,8 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_TIME_UL, "getTime") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_YEAR_UL, "getYear") #endif #if ENABLED (JERRY_BUILTIN_ARRAY) \ -|| ENABLED (JERRY_BUILTIN_STRING) +|| ENABLED (JERRY_BUILTIN_STRING) \ +|| ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_INDEX_OF_UL, "indexOf") #endif #if ENABLED (JERRY_BUILTIN_ARRAY) @@ -604,7 +605,8 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_UTC_MONTH_UL, "getUTCMonth") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_HAS_INSTANCE, "hasInstance") #endif #if ENABLED (JERRY_BUILTIN_ARRAY) \ -|| ENABLED (JERRY_BUILTIN_STRING) +|| ENABLED (JERRY_BUILTIN_STRING) \ +|| ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_LAST_INDEX_OF_UL, "lastIndexOf") #endif #if ENABLED (JERRY_BUILTIN_ARRAY) \ diff --git a/tests/jerry/es2015/typedarray-prototype-indexof.js b/tests/jerry/es2015/typedarray-prototype-indexof.js new file mode 100644 index 000000000..92c017faa --- /dev/null +++ b/tests/jerry/es2015/typedarray-prototype-indexof.js @@ -0,0 +1,104 @@ +/* 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 normal_typedarrays = [ + new Uint8Array([0, 1, 2, 3, 0, 5, 6]), + new Uint16Array([0, 1, 2, 3, 0, 5, 6]), + new Uint32Array([0, 1, 2, 3, 0, 5, 6]), + new Float32Array([0, 1, 2, 3, 0, 5, 6]), + new Float64Array([0, 1, 2, 3, 0, 5, 6]), + new Int8Array([0, 1, 2, 3, 0, 5, 6]), + new Int16Array([0, 1, 2, 3, 0, 5, 6]), + new Int32Array([0, 1, 2, 3, 0, 5, 6]) +]; + +normal_typedarrays.forEach(function(e){ + + try{ + e.prototype.indexOf.call (undefined); + assert (false); + } catch (e) { + assert (e instanceof TypeError); + } + + var index = e.indexOf(0); + assert(index === 0); + assert(e[index] === 0); + + // Regular input + assert(e.indexOf(0, 1) === 4); + assert(e.indexOf(0, 5) === -1); + assert(e.indexOf(3, -2) === -1); + assert(e.indexOf(5, -6) === 5); + assert(e.indexOf(2, -2) === -1); + + // Empty input + assert(e.indexOf() === -1); + + // String input + assert(e.indexOf("foo") === -1); + assert(e.indexOf(3, "foo") === 3); + + // Nan, +/-Infinity + assert(e.indexOf(0, NaN) === 0); + assert(e.indexOf(0, Infinity) === -1); + assert(e.indexOf(3, -Infinity) === 3); + + // Checking behavior when fromIndex is undefined + e.set([1, 2]); + + assert(e.indexOf(2, undefined) === 1); + assert(e.indexOf(2) === 1); + + // Checking behavior when start index >= length + e.set([11, 22, 33, 44]); + + assert(e.indexOf(44, 5) === -1); + + var fromIndex = { + toString: function () { + return {}; + }, + + valueOf: function () { + return {}; + } + }; + + e.set([0, 1]); + + try { + e.indexOf(1, fromIndex); + assert(false); + } catch (e) { + assert(e instanceof TypeError); + } +}); + +// Checking behavior when length is zero +var empty_typedarrays = [ + new Uint8Array([]), + new Uint16Array([]), + new Uint32Array([]), + new Float32Array([]), + new Float64Array([]), + new Int8Array([]), + new Int16Array([]), + new Int32Array([]) +]; + +empty_typedarrays.forEach(function(e){ + assert(e.indexOf(0) === -1); +}); diff --git a/tests/jerry/es2015/typedarray-prototype-lastindexof.js b/tests/jerry/es2015/typedarray-prototype-lastindexof.js new file mode 100644 index 000000000..8a4e280c4 --- /dev/null +++ b/tests/jerry/es2015/typedarray-prototype-lastindexof.js @@ -0,0 +1,102 @@ +// 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 normal_typedarrays = [ + new Uint8Array([0, 1, 2, 3, 0, 5, 6]), + new Uint16Array([0, 1, 2, 3, 0, 5, 6]), + new Uint32Array([0, 1, 2, 3, 0, 5, 6]), + new Float32Array([0, 1, 2, 3, 0, 5, 6]), + new Float64Array([0, 1, 2, 3, 0, 5, 6]), + new Int8Array([0, 1, 2, 3, 0, 5, 6]), + new Int16Array([0, 1, 2, 3, 0, 5, 6]), + new Int32Array([0, 1, 2, 3, 0, 5, 6]) +]; + +normal_typedarrays.forEach(function(e){ + try{ + e.prototype.lastIndexOf.call (undefined); + assert (false); + } catch (e) { + assert (e instanceof TypeError); + } + + var index = e.lastIndexOf(0); + assert(index === 4); + assert(e[index] === 0); + + // Regular input + assert(e.lastIndexOf(0, 3) === 0); + assert(e.lastIndexOf(0, -8) === -1); + assert(e.lastIndexOf(2) === 2); + assert(e.lastIndexOf(5, 3) === -1); + assert(e.lastIndexOf(3, 6) === 3); + + // Empty input + assert(e.lastIndexOf() === -1); + + // String input + assert(e.lastIndexOf("foo") === -1); + assert(e.lastIndexOf(0, "foo") === 0); + + // Nan, +/-Infinity + assert(e.lastIndexOf(0, NaN) === 0); + assert(e.lastIndexOf(0, Infinity) === 4); + assert(e.lastIndexOf(0, -Infinity) === -1); + + // Checking behavior when fromIndex is undefined + e.set([1, 2]); + + assert(e.lastIndexOf(2, undefined) === -1); + assert(e.lastIndexOf(2) === 2); + + // Checking behavior when start index >= length + e.set([11, 22, 33, 44]); + + assert(e.lastIndexOf(44, 8) === 3); + + var fromIndex = { + toString: function () { + return {}; + }, + + valueOf: function () { + return {}; + } + }; + + e.set([0, 1]); + + try { + e.lastIndexOf(1, fromIndex); + assert(false); + } catch (e) { + assert(e instanceof TypeError); + } +}); + +// Checking behavior when length is zero +var empty_typedarrays = [ + new Uint8Array([]), + new Uint16Array([]), + new Uint32Array([]), + new Float32Array([]), + new Float64Array([]), + new Int8Array([]), + new Int16Array([]), + new Int32Array([]) +]; + +empty_typedarrays.forEach(function(e){ + assert(e.lastIndexOf(0) === -1); +});