mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Support for %TypedArray%.prototype.set(typedArray [, offset]). (#2405)
This patch allows developers to set a typedarray given a source typedarray. This patch attempts to follow section 22.2.3.22.2 in the ECMAScript spec as closely as possible. JerryScript-DCO-1.0-Signed-off-by: AnthonyCalandra anthony@anthony-calandra.com
This commit is contained in:
parent
a74bf7dc91
commit
d5cd32b0c0
@ -646,32 +646,148 @@ ecma_builtin_typedarray_prototype_reverse (ecma_value_t this_arg) /**< this argu
|
|||||||
return ecma_copy_value (this_arg);
|
return ecma_copy_value (this_arg);
|
||||||
} /* ecma_builtin_typedarray_prototype_reverse */
|
} /* ecma_builtin_typedarray_prototype_reverse */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The %TypedArray%.prototype object's 'set' routine for a typedArray source
|
||||||
|
*
|
||||||
|
* See also:
|
||||||
|
* ES2015, 22.2.3.22, 22.2.3.22.2
|
||||||
|
*
|
||||||
|
* @return ecma value of undefined if success, error otherwise.
|
||||||
|
* Returned value must be freed with ecma_free_value.
|
||||||
|
*/
|
||||||
|
static ecma_value_t
|
||||||
|
ecma_op_typedarray_set_with_typedarray (ecma_value_t this_arg, /**< this argument */
|
||||||
|
ecma_value_t arr_val, /**< typedarray object */
|
||||||
|
ecma_value_t offset_val) /**< offset value */
|
||||||
|
{
|
||||||
|
/* 6.~ 8. targetOffset */
|
||||||
|
ecma_number_t target_offset_num;
|
||||||
|
if (!ecma_is_value_empty (ecma_get_number (offset_val, &target_offset_num)))
|
||||||
|
{
|
||||||
|
return ecma_raise_range_error (ECMA_ERR_MSG ("Invalid offset"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ecma_number_is_nan (target_offset_num))
|
||||||
|
{
|
||||||
|
target_offset_num = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target_offset_num <= -1.0 || target_offset_num >= (ecma_number_t) UINT32_MAX + 0.5)
|
||||||
|
{
|
||||||
|
return ecma_raise_range_error (ECMA_ERR_MSG ("Invalid offset"));
|
||||||
|
}
|
||||||
|
|
||||||
|
ecma_object_t *target_typedarray_p = ecma_get_object_from_value (this_arg);
|
||||||
|
ecma_object_t *src_typedarray_p = ecma_get_object_from_value (arr_val);
|
||||||
|
|
||||||
|
/* 9. targetBuffer */
|
||||||
|
ecma_object_t *target_arraybuffer_p = ecma_typedarray_get_arraybuffer (target_typedarray_p);
|
||||||
|
lit_utf8_byte_t *target_buffer_p = ecma_typedarray_get_buffer (target_typedarray_p);
|
||||||
|
|
||||||
|
/* 11. targetLength */
|
||||||
|
ecma_length_t target_length = ecma_typedarray_get_length (target_typedarray_p);
|
||||||
|
|
||||||
|
/* 12. srcBuffer */
|
||||||
|
ecma_object_t *src_arraybuffer_p = ecma_typedarray_get_arraybuffer (src_typedarray_p);
|
||||||
|
lit_utf8_byte_t *src_buffer_p = ecma_typedarray_get_buffer (src_typedarray_p);
|
||||||
|
|
||||||
|
/* 15. targetType */
|
||||||
|
lit_magic_string_id_t target_class_id = ecma_object_get_class_name (target_typedarray_p);
|
||||||
|
|
||||||
|
/* 16. targetElementSize */
|
||||||
|
uint8_t target_shift = ecma_typedarray_get_element_size_shift (target_typedarray_p);
|
||||||
|
uint8_t target_element_size = (uint8_t) (1 << target_shift);
|
||||||
|
|
||||||
|
/* 17. targetByteOffset */
|
||||||
|
ecma_length_t target_byte_offset = ecma_typedarray_get_offset (target_typedarray_p);
|
||||||
|
|
||||||
|
/* 19. srcType */
|
||||||
|
lit_magic_string_id_t src_class_id = ecma_object_get_class_name (src_typedarray_p);
|
||||||
|
|
||||||
|
/* 20. srcElementSize */
|
||||||
|
uint8_t src_shift = ecma_typedarray_get_element_size_shift (src_typedarray_p);
|
||||||
|
uint8_t src_element_size = (uint8_t) (1 << src_shift);
|
||||||
|
|
||||||
|
/* 21. srcLength */
|
||||||
|
ecma_length_t src_length = ecma_typedarray_get_length (src_typedarray_p);
|
||||||
|
uint32_t src_length_uint32 = ecma_number_to_uint32 (src_length);
|
||||||
|
|
||||||
|
if ((ecma_number_t) src_length_uint32 != src_length)
|
||||||
|
{
|
||||||
|
return ecma_raise_range_error (ECMA_ERR_MSG ("Invalid source length"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 22. srcByteOffset */
|
||||||
|
ecma_length_t src_byte_offset = ecma_typedarray_get_offset (src_typedarray_p);
|
||||||
|
|
||||||
|
/* 23. */
|
||||||
|
uint32_t target_offset_uint32 = ecma_number_to_uint32 (target_offset_num);
|
||||||
|
|
||||||
|
if ((int64_t) src_length_uint32 + target_offset_uint32 > target_length)
|
||||||
|
{
|
||||||
|
return ecma_raise_range_error (ECMA_ERR_MSG ("Invalid range of index"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 24.d, 25. srcByteIndex */
|
||||||
|
ecma_length_t src_byte_index = 0;
|
||||||
|
|
||||||
|
if (src_arraybuffer_p != target_arraybuffer_p)
|
||||||
|
{
|
||||||
|
src_byte_index = src_byte_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 26. targetByteIndex */
|
||||||
|
uint32_t target_byte_index = target_offset_uint32 * target_element_size + target_byte_offset;
|
||||||
|
|
||||||
|
/* 27. limit */
|
||||||
|
uint32_t limit = target_byte_index + target_element_size * src_length_uint32;
|
||||||
|
|
||||||
|
if (src_class_id == target_class_id)
|
||||||
|
{
|
||||||
|
memmove (target_buffer_p + target_byte_index, src_buffer_p + src_byte_index,
|
||||||
|
target_element_size * src_length_uint32);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (target_byte_index < limit)
|
||||||
|
{
|
||||||
|
ecma_number_t elem_num = ecma_get_typedarray_element (src_buffer_p + src_byte_index, src_class_id);
|
||||||
|
ecma_set_typedarray_element (target_buffer_p + target_byte_index, elem_num, target_class_id);
|
||||||
|
src_byte_index += src_element_size;
|
||||||
|
target_byte_index += target_element_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ECMA_VALUE_UNDEFINED;
|
||||||
|
} /* ecma_op_typedarray_set_with_typedarray */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The %TypedArray%.prototype object's 'set' routine
|
* The %TypedArray%.prototype object's 'set' routine
|
||||||
*
|
*
|
||||||
* See also:
|
* See also:
|
||||||
* ES2015, 22.2.3.22, 22.2.3.22.1
|
* ES2015, 22.2.3.22, 22.2.3.22.1
|
||||||
*
|
*
|
||||||
* @return ecma value of undefined.
|
* @return ecma value of undefined if success, error otherwise.
|
||||||
|
* Returned value must be freed with ecma_free_value.
|
||||||
*/
|
*/
|
||||||
ecma_value_t
|
ecma_value_t
|
||||||
ecma_builtin_typedarray_prototype_set (ecma_value_t this_arg, /**< this argument */
|
ecma_builtin_typedarray_prototype_set (ecma_value_t this_arg, /**< this argument */
|
||||||
ecma_value_t arr_val, /**< array object */
|
ecma_value_t arr_val, /**< array object */
|
||||||
ecma_value_t offset_val) /**< offset value */
|
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. */
|
/* 2.~ 4. */
|
||||||
if (!ecma_is_typedarray (this_arg))
|
if (!ecma_is_typedarray (this_arg))
|
||||||
{
|
{
|
||||||
return ecma_raise_type_error (ECMA_ERR_MSG ("Argument 'this' is not a TypedArray."));
|
return ecma_raise_type_error (ECMA_ERR_MSG ("Argument 'this' is not a TypedArray."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 1. */
|
||||||
|
if (ecma_is_typedarray (arr_val))
|
||||||
|
{
|
||||||
|
/* 22.2.3.22.2 */
|
||||||
|
return ecma_op_typedarray_set_with_typedarray (this_arg, arr_val, offset_val);
|
||||||
|
}
|
||||||
|
|
||||||
/* 6.~ 8. targetOffset */
|
/* 6.~ 8. targetOffset */
|
||||||
ecma_value_t ret_val = ECMA_VALUE_EMPTY;
|
ecma_value_t ret_val = ECMA_VALUE_EMPTY;
|
||||||
ECMA_OP_TO_NUMBER_TRY_CATCH (target_offset_num, offset_val, ret_val);
|
ECMA_OP_TO_NUMBER_TRY_CATCH (target_offset_num, offset_val, ret_val);
|
||||||
|
|||||||
94
tests/jerry/es2015/typedArray-set-with-typedArray.js
Normal file
94
tests/jerry/es2015/typedArray-set-with-typedArray.js
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
/* 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 a = new Int32Array([1, 2, 3, 4, 5]);
|
||||||
|
var b = new Int32Array(5);
|
||||||
|
|
||||||
|
try {
|
||||||
|
a.set(b, 123456);
|
||||||
|
assert(1 === 0); // Should not get here.
|
||||||
|
} catch (e) {
|
||||||
|
assert(e instanceof RangeError);
|
||||||
|
}
|
||||||
|
|
||||||
|
b.set(a);
|
||||||
|
assert(b.join() === '1,2,3,4,5');
|
||||||
|
try {
|
||||||
|
b.set(a, 1);
|
||||||
|
assert(1 === 0); // Should not get here.
|
||||||
|
} catch (e) {
|
||||||
|
assert(e instanceof RangeError);
|
||||||
|
}
|
||||||
|
|
||||||
|
b.set(new Int32Array([99, 98]), 2);
|
||||||
|
assert(b.join() === '1,2,99,98,5');
|
||||||
|
|
||||||
|
b.set(new Int32Array([99, 98, 97]), 2);
|
||||||
|
assert(b.join() === '1,2,99,98,97');
|
||||||
|
|
||||||
|
try {
|
||||||
|
b.set(new Int32Array([99, 98, 97, 96]), 2);
|
||||||
|
assert(1 === 0); // Should not get here.
|
||||||
|
} catch (e) {
|
||||||
|
assert(e instanceof RangeError);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
b.set([101, 102, 103, 104], 4);
|
||||||
|
assert(1 === 0); // Should not get here.
|
||||||
|
} catch (e) {
|
||||||
|
assert(e instanceof RangeError);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ab = [ 0, 1, 2, 3, 4, 5, 6, 7 ]
|
||||||
|
// a1 = [ ^, ^, ^, ^, ^, ^, ^, ^ ]
|
||||||
|
// a2 = [ ^, ^, ^, ^ ]
|
||||||
|
var ab = new ArrayBuffer(8);
|
||||||
|
var a1 = new Uint8Array(ab);
|
||||||
|
for (var i = 0; i < a1.length; i += 1) {
|
||||||
|
a1.set([i], i);
|
||||||
|
}
|
||||||
|
|
||||||
|
var a2 = new Uint8Array(ab, 4);
|
||||||
|
a1.set(a2, 2);
|
||||||
|
assert(a1.join() === '0,1,4,5,6,7,6,7');
|
||||||
|
assert(a2.join() === '6,7,6,7');
|
||||||
|
|
||||||
|
var a3 = new Uint32Array(ab, 4);
|
||||||
|
a1.set(a3, 2);
|
||||||
|
assert(a1.join() === '0,1,6,5,6,7,6,7');
|
||||||
|
assert(a3.join() === '117835526');
|
||||||
|
|
||||||
|
var a4 = new Uint8Array(ab, 0, 4);
|
||||||
|
a1.set(a4, 2);
|
||||||
|
assert(a1.join() === '0,1,0,1,6,5,6,7');
|
||||||
|
assert(a4.join() === '0,1,0,1');
|
||||||
|
|
||||||
|
var a5 = new Uint32Array(ab, 4, 1);
|
||||||
|
a1.set(a5, 2);
|
||||||
|
assert(a1.join() === '0,1,6,1,6,5,6,7');
|
||||||
|
assert(a5.join() === '117835014');
|
||||||
|
|
||||||
|
var c = new Int32Array([0xFFFFFFFF]);
|
||||||
|
var d = new Uint8Array(4);
|
||||||
|
d.set(c);
|
||||||
|
assert(d.join() === '255,0,0,0');
|
||||||
|
|
||||||
|
var e = new Float32Array([3.33]);
|
||||||
|
var f = new Uint8Array(1);
|
||||||
|
f.set(e);
|
||||||
|
assert(f.join() === '3');
|
||||||
|
e.set(f);
|
||||||
|
assert(e.join() === '3');
|
||||||
Loading…
x
Reference in New Issue
Block a user