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 ea8e8d9b5e..7e4fd9728e 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 @@ -647,6 +647,116 @@ ecma_builtin_typedarray_prototype_reverse (ecma_value_t this_arg) /**< this argu return ecma_copy_value (this_arg); } /* ecma_builtin_typedarray_prototype_reverse */ +/** + * The %TypedArray%.prototype object's 'set' routine + * + * See also: + * ES2015, 22.2.3.22, 22.2.3.22.1 + * + * @return ecma value of undefined. + */ +ecma_value_t +ecma_builtin_typedarray_prototype_set (ecma_value_t this_arg, /**< this argument */ + ecma_value_t arr_val, /**< array object */ + ecma_value_t offset_val) /**< offset value */ +{ + /* 1. */ + if (ecma_is_typedarray (arr_val)) + { + /* 22.2.3.22.2 %TypedArray%.prototype(typedArray [, offset ]) is not supported */ + return ecma_raise_type_error (ECMA_ERR_MSG ("TypedArray.set(typedArray [,offset]) is not supported.")); + } + + /* 2.~ 4. */ + if (!ecma_is_typedarray (this_arg)) + { + return ecma_raise_type_error (ECMA_ERR_MSG ("Argument 'this' is not a TypedArray.")); + } + + /* 6.~ 8. targetOffset */ + ecma_value_t ret_val = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); + ECMA_OP_TO_NUMBER_TRY_CATCH (target_offset_num, offset_val, ret_val); + if (ecma_number_is_nan (target_offset_num)) + { + target_offset_num = 0; + } + if (target_offset_num <= -1.0 || target_offset_num >= (double) UINT32_MAX + 0.5) + { + return ecma_raise_range_error (ECMA_ERR_MSG ("Invalid offset")); + } + uint32_t target_offset_uint32 = ecma_number_to_uint32 (target_offset_num); + + /* 11. targetLength */ + ecma_object_t *typedarray_p = ecma_get_object_from_value (this_arg); + ecma_length_t target_length = ecma_typedarray_get_length (typedarray_p); + + /* 13. targetElementSize */ + uint8_t shift = ecma_typedarray_get_element_size_shift (typedarray_p); + uint8_t element_size = (uint8_t) (1 << shift); + + /* 14. targetType */ + lit_magic_string_id_t target_class_id = ecma_object_get_class_name (typedarray_p); + + /* 9., 15. */ + lit_utf8_byte_t *target_buffer_p = ecma_typedarray_get_buffer (typedarray_p); + + /* 16.~ 17. */ + ECMA_TRY_CATCH (source_obj, ecma_op_to_object (arr_val), ret_val); + + /* 18.~ 19. */ + ecma_string_t length_str; + ecma_init_ecma_length_string (&length_str); + ecma_object_t *source_obj_p = ecma_get_object_from_value (source_obj); + ECMA_TRY_CATCH (source_length, + ecma_op_object_get (source_obj_p, &length_str), + ret_val); + ECMA_OP_TO_NUMBER_TRY_CATCH (source_length_num, source_length, ret_val); + if (ecma_number_is_nan (source_length_num) || source_length_num <= 0) + { + source_length_num = 0; + } + uint32_t source_length_uint32 = ecma_number_to_uint32 (source_length_num); + if ((ecma_number_t) source_length_uint32 != source_length_num) + { + return ecma_raise_range_error (ECMA_ERR_MSG ("Invalid source length")); + } + + /* 20. if srcLength + targetOffset > targetLength, throw a RangeError */ + if ((int64_t) source_length_uint32 + target_offset_uint32 > target_length) + { + ret_val = ecma_raise_range_error (ECMA_ERR_MSG ("Invalid range of index")); + } + + /* 21.~ 25. */ + uint32_t target_byte_index = target_offset_uint32 * element_size; + uint32_t k = 0; + while (k < source_length_uint32 && ecma_is_value_empty (ret_val)) + { + ecma_string_t k_str; + ecma_init_ecma_string_from_uint32 (&k_str, k); + ECMA_TRY_CATCH (elem, + ecma_op_object_get (source_obj_p, &k_str), + ret_val); + ECMA_OP_TO_NUMBER_TRY_CATCH (elem_num, elem, ret_val); + ecma_set_typedarray_element (target_buffer_p + target_byte_index, elem_num, target_class_id); + ECMA_OP_TO_NUMBER_FINALIZE (elem_num); + ECMA_FINALIZE (elem); + k++; + target_byte_index += element_size; + } + + ECMA_OP_TO_NUMBER_FINALIZE (source_length_num); + ECMA_FINALIZE (source_length); + ECMA_FINALIZE (source_obj); + ECMA_OP_TO_NUMBER_FINALIZE (target_offset_num); + + if (ecma_is_value_empty (ret_val)) + { + ret_val = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED); + } + return ret_val; +} /* ecma_builtin_typedarray_prototype_set */ + /** * @} * @} 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 47a9794ce1..60dffd9c06 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 @@ -53,6 +53,7 @@ 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) ROUTINE (LIT_MAGIC_STRING_FILTER, ecma_builtin_typedarray_prototype_filter, 2, 1) ROUTINE (LIT_MAGIC_STRING_REVERSE, ecma_builtin_typedarray_prototype_reverse, 0, 0) +ROUTINE (LIT_MAGIC_STRING_SET, ecma_builtin_typedarray_prototype_set, 2, 1) #endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */ diff --git a/jerry-core/ecma/operations/ecma-typedarray-object.c b/jerry-core/ecma/operations/ecma-typedarray-object.c index 0d2e3f6b3a..ae4011dd0e 100644 --- a/jerry-core/ecma/operations/ecma-typedarray-object.c +++ b/jerry-core/ecma/operations/ecma-typedarray-object.c @@ -49,9 +49,9 @@ * * @return ecma_number_t: the value of the element */ -static ecma_number_t -get_typedarray_element (lit_utf8_byte_t *src, /**< the location in the internal arraybuffer */ - lit_magic_string_id_t class_id) /**< class name of the typedarray */ +ecma_number_t +ecma_get_typedarray_element (lit_utf8_byte_t *src, /**< the location in the internal arraybuffer */ + lit_magic_string_id_t class_id) /**< class name of the typedarray */ { switch (class_id) { @@ -96,17 +96,17 @@ get_typedarray_element (lit_utf8_byte_t *src, /**< the location in the internal return 0; } } -} /* get_typedarray_element */ +} /* ecma_get_typedarray_element */ #undef GET_ELEMENT /** * set typedarray's element value */ -static void -set_typedarray_element (lit_utf8_byte_t *dst_p, /**< the location in the internal arraybuffer */ - ecma_number_t value, /**< the number value to set */ - lit_magic_string_id_t class_id) /**< class name of the typedarray */ +void +ecma_set_typedarray_element (lit_utf8_byte_t *dst_p, /**< the location in the internal arraybuffer */ + ecma_number_t value, /**< the number value to set */ + lit_magic_string_id_t class_id) /**< class name of the typedarray */ { switch (class_id) { @@ -215,7 +215,7 @@ set_typedarray_element (lit_utf8_byte_t *dst_p, /**< the location in the interna JERRY_UNREACHABLE (); } } -} /* set_typedarray_element */ +} /* ecma_set_typedarray_element */ /** * Create a TypedArray object by given array_length @@ -352,8 +352,8 @@ ecma_typedarray_create_object_with_typedarray (ecma_object_t *typedarray_p, /**< for (uint32_t i = 0; i < array_length; i++) { /* Convert values from source to destination format. */ - ecma_number_t tmp = get_typedarray_element (src_buf_p, src_class_id); - set_typedarray_element (dst_buf_p, tmp, class_id); + ecma_number_t tmp = ecma_get_typedarray_element (src_buf_p, src_class_id); + ecma_set_typedarray_element (dst_buf_p, tmp, class_id); src_buf_p += src_element_size; dst_buf_p += dst_element_size; @@ -486,7 +486,7 @@ ecma_op_typedarray_from (ecma_value_t items_val, /**< the source array-like obje } /* ecma_op_typedarray_from */ /** - * Get the array length of the typedarray object + * Get the arraybuffer of the typedarray object * * @return the pointer to the internal arraybuffer */ @@ -810,7 +810,7 @@ ecma_op_typedarray_get_index_prop (ecma_object_t *obj_p, /**< a TypedArray objec ecma_length_t byte_pos = (index << shift) + offset; lit_magic_string_id_t class_id = ecma_object_get_class_name (obj_p); lit_utf8_byte_t *target_p = ecma_arraybuffer_get_buffer (arraybuffer_p) + byte_pos; - ecma_number_t value = get_typedarray_element (target_p, class_id); + ecma_number_t value = ecma_get_typedarray_element (target_p, class_id); return ecma_make_number_value (value); } /* ecma_op_typedarray_get_index_prop */ @@ -889,7 +889,7 @@ ecma_op_typedarray_set_index_prop (ecma_object_t *obj_p, /**< a TypedArray objec ecma_length_t byte_pos = (index << shift) + offset; lit_magic_string_id_t class_id = ecma_object_get_class_name (obj_p); lit_utf8_byte_t *target_p = ecma_arraybuffer_get_buffer (arraybuffer_p) + byte_pos; - set_typedarray_element (target_p, value_num, class_id); + ecma_set_typedarray_element (target_p, value_num, class_id); ECMA_OP_TO_NUMBER_FINALIZE (value_num); diff --git a/jerry-core/ecma/operations/ecma-typedarray-object.h b/jerry-core/ecma/operations/ecma-typedarray-object.h index 31bb5bd7a2..078b5f939e 100644 --- a/jerry-core/ecma/operations/ecma-typedarray-object.h +++ b/jerry-core/ecma/operations/ecma-typedarray-object.h @@ -43,6 +43,11 @@ ecma_value_t ecma_op_create_typedarray (const ecma_value_t *arguments_list_p, uint8_t element_size_shift, lit_magic_string_id_t class_id); bool ecma_is_typedarray (ecma_value_t target); +void ecma_set_typedarray_element (lit_utf8_byte_t *dst_p, + ecma_number_t value, + lit_magic_string_id_t class_id); +ecma_number_t ecma_get_typedarray_element (lit_utf8_byte_t *src, + lit_magic_string_id_t class_id); void ecma_op_typedarray_list_lazy_property_names (ecma_object_t *obj_p, ecma_collection_header_t *main_collection_p); ecma_value_t ecma_op_typedarray_get_index_prop (ecma_object_t *obj_p, uint32_t index); diff --git a/tests/jerry-test-suite/es2015/22/22.02/22.02.03/22.02.03-019.js b/tests/jerry-test-suite/es2015/22/22.02/22.02.03/22.02.03-019.js new file mode 100644 index 0000000000..4520b69e8e --- /dev/null +++ b/tests/jerry-test-suite/es2015/22/22.02/22.02.03/22.02.03-019.js @@ -0,0 +1,74 @@ +/* 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 uint8 = new Uint8Array(4); + +// 22.2.3.22 +assert(uint8.set.length === 1) + +try +{ + uint8.set([1], -1); + assert(false); +} catch (e) +{ + assert(e instanceof RangeError); +} + +try +{ + uint8.set([1], - (Math.pow(2, 32) + 1)); + assert(false); +} catch (e) +{ + assert(e instanceof RangeError); +} + +try +{ + uint8.set([1], -Infinity); + assert(false); +} catch (e) +{ + assert(e instanceof RangeError); +} + +try +{ + uint8.set([1], Infinity); + assert(false); +} catch (e) +{ + assert(e instanceof RangeError); +} + +try +{ + uint8.set([1], (Math.pow(2, 32) + 1)); + assert(false); +} catch (e) +{ + assert(e instanceof RangeError); +} + +try +{ + // 22.2.3.22.1 step 20 + uint8.set([17, 18, 19], 2); + assert(false); +} catch (e) +{ + assert(e instanceof RangeError) +} diff --git a/tests/jerry-test-suite/es2015/22/22.02/22.02.03/22.02.03-020.js b/tests/jerry-test-suite/es2015/22/22.02/22.02.03/22.02.03-020.js new file mode 100644 index 0000000000..2608e8d41e --- /dev/null +++ b/tests/jerry-test-suite/es2015/22/22.02/22.02.03/22.02.03-020.js @@ -0,0 +1,53 @@ +/* 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 uint8 = new Uint8Array(4); + +uint8.set([10, "11", 12]); +assert(uint8[0] === 10 && uint8[1] === 11 && uint8[2] === 12); + +uint8.set([13, 14.3, 15], 1); +assert(uint8[0] === 10 && uint8[1] === 13 && uint8[2] === 14 && uint8[3] === 15); + +uint8.set([16], NaN); +assert(uint8[0] === 16 && uint8[1] === 13 && uint8[2] === 14 && uint8[3] === 15); + +uint8.set([17], ""); +assert(uint8[0] === 17 && uint8[1] === 13 && uint8[2] === 14 && uint8[3] === 15); + +uint8.set([18], "0"); +assert(uint8[0] === 18 && uint8[1] === 13 && uint8[2] === 14 && uint8[3] === 15); + +uint8.set([19], false); +assert(uint8[0] === 19 && uint8[1] === 13 && uint8[2] === 14 && uint8[3] === 15); + +uint8.set([20], 0.2); +assert(uint8[0] === 20 && uint8[1] === 13 && uint8[2] === 14 && uint8[3] === 15); + +uint8.set([21], 0.9); +assert(uint8[0] === 21 && uint8[1] === 13 && uint8[2] === 14 && uint8[3] === 15); + +uint8.set([22], null); +assert(uint8[0] === 22 && uint8[1] === 13 && uint8[2] === 14 && uint8[3] === 15); + +uint8.set([23], {}); +assert(uint8[0] === 23 && uint8[1] === 13 && uint8[2] === 14 && uint8[3] === 15); + +uint8.set([24], []); +assert(uint8[0] === 24 && uint8[1] === 13 && uint8[2] === 14 && uint8[3] === 15); + +uint8.set([25], true); +assert(uint8[0] === 24 && uint8[1] === 25 && uint8[2] === 14 && uint8[3] === 15); + diff --git a/tests/jerry-test-suite/es2015/22/22.02/22.02.03/22.02.03-021.js b/tests/jerry-test-suite/es2015/22/22.02/22.02.03/22.02.03-021.js new file mode 100644 index 0000000000..82d4ee0a17 --- /dev/null +++ b/tests/jerry-test-suite/es2015/22/22.02/22.02.03/22.02.03-021.js @@ -0,0 +1,31 @@ +/* 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 float64 = new Float64Array(4); +float64.set([10.1, "11.2", 12.3]); +assert(float64[0] === 10.1 && float64[1] === 11.2 && float64[2] === 12.3); + +float64.set([13.1, 14.2, 15.3], 1); +assert(float64[0] === 10.1 && float64[1] === 13.1 && float64[2] === 14.2 && float64[3] === 15.3); + +try +{ + // 22.2.3.22.1 step 20 + float64.set([17.1, 18.2, 19.3], 2); + assert(false); +} catch (e) +{ + assert(e instanceof RangeError) +}