From ff36f3579d846c62dd85538d861153b8f432d74e Mon Sep 17 00:00:00 2001 From: Szilagyi Adam Date: Mon, 27 Jul 2020 18:09:39 +0200 Subject: [PATCH] Implement %TypedArray%.prototype.includes (#4025) The algorithm is based on ECMA-262 v11, 22.2.3.13 JerryScript-DCO-1.0-Signed-off-by: Adam Szilagyi aszilagy@inf.u-szeged.hu --- .../ecma-builtin-typedarray-prototype.c | 61 +++++++++++++++++++ .../ecma-builtin-typedarray-prototype.inc.h | 1 + jerry-core/lit/lit-magic-strings.inc.h | 3 +- .../es.next/typedarray-prototype-includes.js | 55 +++++++++++++++++ 4 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 tests/jerry/es.next/typedarray-prototype-includes.js 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 5f9795e04..1da28f126 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 @@ -2025,6 +2025,67 @@ ecma_builtin_typedarray_prototype_to_locale_string (ecma_value_t this_arg) /**< return ecma_make_string_value (ecma_stringbuilder_finalize (&builder)); } /* ecma_builtin_typedarray_prototype_to_locale_string */ +/** + * The %TypedArray%.prototype object's 'includes' routine + * + * See also: + * ECMA-262 v11, 22.2.3.13. + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_typedarray_prototype_includes (ecma_value_t this_arg, /**< this argument */ + const ecma_value_t args[], /**< arguments list */ + uint32_t args_number) /**< number of arguments */ +{ + 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); + ecma_typedarray_info_t info = ecma_typedarray_get_info (typedarray_p); + uint32_t limit = info.length * info.element_size; + + if (args_number == 0 + || !ecma_is_value_number (args[0]) + || info.length == 0) + { + return ECMA_VALUE_FALSE; + } + + uint32_t from_index = 0; + + if (args_number > 1) + { + if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (args[1], info.length, &from_index))) + { + return ECMA_VALUE_ERROR; + } + } + + ecma_number_t search_num = ecma_get_number_from_value (args[0]); + + ecma_typedarray_getter_fn_t getter_cb = ecma_get_typedarray_getter_fn (info.id); + + uint32_t search_pos = (uint32_t) from_index * info.element_size; + + while (search_pos < limit) + { + ecma_number_t element_num = getter_cb (info.buffer_p + search_pos); + + if (search_num == element_num) + { + return ECMA_VALUE_TRUE; + } + + search_pos += info.element_size; + } + + return ECMA_VALUE_FALSE; +} /* ecma_builtin_typedarray_prototype_includes */ + /** * @} * @} 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 6d1fce369..ff1f26c62 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 @@ -80,6 +80,7 @@ INTRINSIC_PROPERTY (LIT_MAGIC_STRING_VALUES, LIT_INTERNAL_MAGIC_STRING_TYPEDARRA ECMA_PROPERTY_CONFIGURABLE_WRITABLE) INTRINSIC_PROPERTY (LIT_GLOBAL_SYMBOL_ITERATOR, LIT_INTERNAL_MAGIC_STRING_TYPEDARRAY_PROTOTYPE_VALUES, ECMA_PROPERTY_CONFIGURABLE_WRITABLE) +ROUTINE (LIT_MAGIC_STRING_INCLUDES, ecma_builtin_typedarray_prototype_includes, NON_FIXED, 1) #endif /* ENABLED (JERRY_BUILTIN_TYPEDARRAY) */ diff --git a/jerry-core/lit/lit-magic-strings.inc.h b/jerry-core/lit/lit-magic-strings.inc.h index bf9a1cc84..40bdab6fe 100644 --- a/jerry-core/lit/lit-magic-strings.inc.h +++ b/jerry-core/lit/lit-magic-strings.inc.h @@ -553,7 +553,8 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_MONTH_UL, "getMonth") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_UINT8_UL, "getUint8") #endif #if ENABLED (JERRY_BUILTIN_ARRAY) && ENABLED (JERRY_ESNEXT) \ -|| ENABLED (JERRY_BUILTIN_STRING) && ENABLED (JERRY_ESNEXT) +|| ENABLED (JERRY_BUILTIN_STRING) && ENABLED (JERRY_ESNEXT) \ +|| ENABLED (JERRY_BUILTIN_TYPEDARRAY) LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_INCLUDES, "includes") #endif LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_IS_FINITE, "isFinite") diff --git a/tests/jerry/es.next/typedarray-prototype-includes.js b/tests/jerry/es.next/typedarray-prototype-includes.js new file mode 100644 index 000000000..0407a8d86 --- /dev/null +++ b/tests/jerry/es.next/typedarray-prototype-includes.js @@ -0,0 +1,55 @@ +// 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 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]) +]; + +typedarrays.forEach(function(e){ + assert(e.includes.length === 1); + assert(e.includes.name === "includes"); + assert(e.includes() === false); + assert(e.includes("foo") === false); + assert(e.includes(undefined) === false); + assert(e.includes(NaN) === false); + assert(e.includes(0) === true); + assert(e.includes(0, 4) === true); + assert(e.includes(0, 5) === false); + assert(e.includes(1, Infinity) === false); + assert(e.includes(1, -Infinity) === true); + assert(e.includes(6, 8) === false); + assert(e.includes(3, -5) === true); +}); + +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.includes(5) === false); +});