Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1797,6 +1797,187 @@ ecma_builtin_typedarray_prototype_last_index_of (ecma_value_t this_arg, /**< thi
return ecma_builtin_typedarray_prototype_index_helper (this_arg, args, args_number, true);
} /* ecma_builtin_typedarray_prototype_last_index_of */

/**
* Helper function to get the uint32_t value from an argument.
*
* @return ecma value
* Returned value must be freed with ecma_free_value.
*/
static ecma_value_t
ecma_builtin_get_uint32_value_from_argument (ecma_value_t arg_value, /**< this argument */
uint32_t length, /**< length of the TypedArray */
uint32_t *index, /**< [out] pointer to the given index */
bool is_end_index) /**< true - normalize the end index */
{
ecma_number_t num_var;
ecma_value_t ret_value = ecma_get_number (arg_value, &num_var);

if (ECMA_IS_VALUE_ERROR (ret_value))
{
return ret_value;
}

if (is_end_index && ecma_number_is_nan (num_var))
{
*index = length;
}
else
{
*index = ecma_builtin_helper_array_index_normalize (num_var, length, false);
}

return ECMA_VALUE_EMPTY;
} /* ecma_builtin_get_uint32_value_from_argument */

/**
* The %TypedArray%.prototype object's 'copyWithin' routine
*
* See also:
* ECMA-262 v6, 22.2.3.5
*
* @return ecma value
* Returned value must be freed with ecma_free_value.
*/
static ecma_value_t
ecma_builtin_typedarray_prototype_copy_within (ecma_value_t this_arg, /**< this argument */
const ecma_value_t args[], /**< arguments list */
ecma_length_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);
lit_utf8_byte_t *typedarray_buffer_p = ecma_typedarray_get_buffer (typedarray_p);
uint32_t length = ecma_typedarray_get_length (typedarray_p);
uint8_t shift = ecma_typedarray_get_element_size_shift (typedarray_p);
uint8_t element_size = (uint8_t) (1 << shift);
uint32_t target = 0;
uint32_t start = 0;
uint32_t end = length;

if (args_number > 0)
{
ecma_value_t target_value = ecma_builtin_get_uint32_value_from_argument (args[0], length, &target, false);

if (ECMA_IS_VALUE_ERROR (target_value))
{
return target_value;
}

if (args_number > 1)
{
ecma_value_t start_value = ecma_builtin_get_uint32_value_from_argument (args[1], length, &start, false);

if (ECMA_IS_VALUE_ERROR (start_value))
{
return start_value;
}

if (args_number > 2)
{
ecma_value_t end_value = ecma_builtin_get_uint32_value_from_argument (args[2], length, &end, true);

if (ECMA_IS_VALUE_ERROR (end_value))
{
return end_value;
}
}
}
}

int32_t distance = (int32_t) (end - start);
int32_t offset = (int32_t) (length - target);
int32_t count = JERRY_MIN (distance, offset);

if (target >= length || start >= length || end == 0)
{
return ecma_copy_value (this_arg);
}
else
{
memmove (typedarray_buffer_p + (target * element_size),
typedarray_buffer_p + (start * element_size),
(size_t) (count * element_size));
}

return ecma_copy_value (this_arg);
} /* ecma_builtin_typedarray_prototype_copy_within */

/**
* The %TypedArray%.prototype object's 'slice' routine
*
* See also:
* ECMA-262 v6, 22.2.3.23
*
* @return ecma value
* Returned value must be freed with ecma_free_value.
*/
static ecma_value_t
ecma_builtin_typedarray_prototype_slice (ecma_value_t this_arg, /**< this argument */
const ecma_value_t args[], /**< arguments list */
ecma_length_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);
uint32_t length = ecma_typedarray_get_length (typedarray_p);
uint32_t start = 0;
uint32_t end = length;

if (args_number > 0)
{
ecma_value_t start_value = ecma_builtin_get_uint32_value_from_argument (args[0], length, &start, false);

if (ECMA_IS_VALUE_ERROR (start_value))
{
return start_value;
}

if (args_number > 1)
{
ecma_value_t end_value = ecma_builtin_get_uint32_value_from_argument (args[1], length, &end, true);

if (ECMA_IS_VALUE_ERROR (end_value))
{
return end_value;
}
}
}

int32_t distance = (int32_t) (end - start);
uint32_t count = distance > 0 ? (uint32_t) distance : 0;

ecma_value_t new_typedarray = ecma_op_create_typedarray_with_type_and_length (typedarray_p, count);

if (ECMA_IS_VALUE_ERROR (new_typedarray))
{
return new_typedarray;
}

if (count > 0)
{
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);

ecma_object_t *new_typedarray_p = ecma_get_object_from_value (new_typedarray);
lit_utf8_byte_t *new_typedarray_buffer_p = ecma_typedarray_get_buffer (new_typedarray_p);
ecma_length_t src_byte_offset = ecma_typedarray_get_offset (typedarray_p);
uint32_t src_byte_index = (start * element_size) + src_byte_offset;

memcpy (new_typedarray_buffer_p,
typedarray_buffer_p + src_byte_index,
count * element_size);
}

return new_typedarray;
} /* ecma_builtin_typedarray_prototype_slice */

/**
* @}
* @}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ 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)
ROUTINE (LIT_MAGIC_STRING_COPY_WITHIN, ecma_builtin_typedarray_prototype_copy_within, NON_FIXED, 2)
ROUTINE (LIT_MAGIC_STRING_SLICE, ecma_builtin_typedarray_prototype_slice, NON_FIXED, 2)

#if ENABLED (JERRY_ES2015_BUILTIN_ITERATOR)

Expand Down
5 changes: 5 additions & 0 deletions jerry-core/lit/lit-magic-strings.inc.h
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,9 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BYTE_OFFSET_UL, "byteOffset")
#if ENABLED (JERRY_BUILTIN_STRING)
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CHAR_CODE_AT_UL, "charCodeAt")
#endif
#if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_COPY_WITHIN, "copyWithin")
#endif
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ENUMERABLE, "enumerable")
#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW)
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_FLOAT_32_UL, "getFloat32")
Expand Down Expand Up @@ -804,6 +807,8 @@ LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (10, LIT_MAGIC_STRING_TYPED_ARRAY_UL)
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (10, LIT_MAGIC_STRING_BYTE_LENGTH_UL)
#elif ENABLED (JERRY_BUILTIN_STRING)
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (10, LIT_MAGIC_STRING_CHAR_CODE_AT_UL)
#elif ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (10, LIT_MAGIC_STRING_COPY_WITHIN)
#else
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (10, LIT_MAGIC_STRING_ENUMERABLE)
#endif
Expand Down
1 change: 1 addition & 0 deletions jerry-core/lit/lit-magic-strings.ini
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ LIT_MAGIC_STRING_UINT8_ARRAY_UL = "Uint8Array"
LIT_MAGIC_STRING_BYTE_LENGTH_UL = "byteLength"
LIT_MAGIC_STRING_BYTE_OFFSET_UL = "byteOffset"
LIT_MAGIC_STRING_CHAR_CODE_AT_UL = "charCodeAt"
LIT_MAGIC_STRING_COPY_WITHIN = "copyWithin"
LIT_MAGIC_STRING_ENUMERABLE = "enumerable"
LIT_MAGIC_STRING_GET_FLOAT_32_UL = "getFloat32"
LIT_MAGIC_STRING_GET_FLOAT_64_UL = "getFloat64"
Expand Down
74 changes: 74 additions & 0 deletions tests/jerry/es2015/typedarray-prototype-copy-within.js
Original file line number Diff line number Diff line change
@@ -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 typedarrays = [
new Uint8ClampedArray ([0, 1, 2, 3, 4, 5]),
new Uint8Array([0, 1, 2, 3, 4, 5]),
new Uint16Array([0, 1, 2, 3, 4, 5]),
new Uint32Array([0, 1, 2, 3, 4, 5]),
new Float32Array([0, 1, 2, 3, 4, 5]),
new Float64Array([0, 1, 2, 3, 4, 5]),
new Int8Array([0, 1, 2, 3, 4, 5]),
new Int16Array([0, 1, 2, 3, 4, 5]),
new Int32Array([0, 1, 2, 3, 4, 5])
];

typedarrays.forEach(function(e){
try {
e.prototype.copyWithin.call (undefined);
assert (false);
} catch (err) {
assert (err instanceof TypeError);
}

// Test with normal inputs
assert(e.copyWithin(2, 1 ,4).toString() === '0,1,1,2,3,5');
assert(e.copyWithin(3, 4, 6).toString() === '0,1,1,3,5,5');
assert(e.copyWithin(4, 1, 3).toString() === '0,1,1,3,1,1');

e.set([5, 2, 1, 3, 4, 4]);

// Test with negative inputs
assert(e.copyWithin(2, -10, 3).toString() === '5,2,5,2,1,4');
assert(e.copyWithin(-3, 1, 6).toString() === '5,2,5,2,5,2');
assert(e.copyWithin(2, 0, -3).toString() === '5,2,5,2,5,2');

e.set([9, 3, 4, 5, 1, 7]);

// Test with default inputs
assert(e.copyWithin().toString() === '9,3,4,5,1,7');
assert(e.copyWithin(3).toString() === '9,3,4,9,3,4');
assert(e.copyWithin(1, 5).toString() === '9,4,4,9,3,4');

e.set([12, 3, 1, 43, 2, 9]);

// Test with too big inputs
assert(e.copyWithin(2, 12, 21).toString() === '12,3,1,43,2,9');
assert(e.copyWithin(4, 5, 13).toString() === '12,3,1,43,9,9');

e.set([1, 2, 3, 1, 2, 1]);

// Test with undefined inputs
assert(e.copyWithin(undefined, 2, 4).toString() === '3,1,3,1,2,1');
assert(e.copyWithin(undefined, undefined, 2).toString() === '3,1,3,1,2,1');
assert(e.copyWithin(3, undefined, 5).toString() === '3,1,3,3,1,3');

e.set([0, 2, 4, 2, 1, 5]);

// Test with NaN/+-Infinity
assert(e.copyWithin(NaN, 3, 5).toString() === '2,1,4,2,1,5');
assert(e.copyWithin(3, Infinity, 5).toString() === '2,1,4,2,1,5');
assert(e.copyWithin(1, 3, -Infinity).toString() === '2,1,4,2,1,5');
});
63 changes: 63 additions & 0 deletions tests/jerry/es2015/typedarray-prototype-slice.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/* 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 Uint8ClampedArray([0, 1, 2, 3, 4, 5]),
new Uint8Array([0, 1, 2, 3, 4, 5]),
new Uint16Array([0, 1, 2, 3, 4, 5]),
new Uint32Array([0, 1, 2, 3, 4, 5]),
new Float32Array([0, 1, 2, 3, 4, 5]),
new Float64Array([0, 1, 2, 3, 4, 5]),
new Int8Array([0, 1, 2, 3, 4, 5]),
new Int16Array([0, 1, 2, 3, 4, 5]),
new Int32Array([0, 1, 2, 3, 4, 5])
];

typedarrays.forEach(function(e){
try {
e.prototype.slice.call (undefined);
assert (false);
} catch (err) {
assert (err instanceof TypeError);
}

// Test with normal inputs
assert(e.slice(1, 3).toString() === "1,2");
assert(e.slice(2, 5).toString() === "2,3,4");
assert(e.slice(0, 6).toString() === "0,1,2,3,4,5");

// Test witn negative inputs
assert(e.slice(-2, 5).toString() === "4");
assert(e.slice(0, -3).toString() === "0,1,2");
assert(e.slice(-1, -4).toString() === "");

// Test with bigger inputs then length
assert(e.slice(7, 1).toString() === "");
assert(e.slice(2, 9).toString() === "2,3,4,5");

// Test with undefined
assert(e.slice(undefined, 4).toString() === "0,1,2,3");
assert(e.slice(0, undefined).toString() === "0,1,2,3,4,5");
assert(e.slice(undefined, undefined).toString() === "0,1,2,3,4,5");

// Test with NaN and +/-Infinity
assert(e.slice(NaN, 3).toString() === "0,1,2");
assert(e.slice(2, Infinity).toString() === "2,3,4,5");
assert(e.slice(-Infinity, Infinity).toString() === "0,1,2,3,4,5");

// Test with default inputs
assert(e.slice().toString() === "0,1,2,3,4,5");
assert(e.slice(4).toString() === "4,5");
});