Implement typedarary.set(array, offset)

JerryScript-DCO-1.0-Signed-off-by: Sanggyu Lee sg5.lee@samsung.com
This commit is contained in:
Sanggyu Lee 2017-07-07 15:03:40 +09:00 committed by yichoi
parent a48f24f8da
commit af16a3ae1a
7 changed files with 288 additions and 14 deletions

View File

@ -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 */
/**
* @}
* @}

View File

@ -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 */

View File

@ -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);

View File

@ -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);

View File

@ -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)
}

View File

@ -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);

View File

@ -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)
}