Implement Array.prototype's copyWithin method (#3269)

The algorithm is based on ECMA-262 v6, 22.1.3.3

JerryScript-DCO-1.0-Signed-off-by: Adam Szilagyi aszilagy@inf.u-szeged.hu
This commit is contained in:
Szilagyi Adam
2019-11-08 15:41:20 +01:00
committed by Robert Fancsik
parent dc458111ba
commit 798655a871
4 changed files with 220 additions and 2 deletions
@@ -77,6 +77,7 @@ enum
ECMA_ARRAY_PROTOTYPE_KEYS,
ECMA_ARRAY_PROTOTYPE_SYMBOL_ITERATOR,
ECMA_ARRAY_PROTOTYPE_FILL,
ECMA_ARRAY_PROTOTYPE_COPY_WITHIN,
};
#define BUILTIN_INC_HEADER_NAME "ecma-builtin-array-prototype.inc.h"
@@ -2268,6 +2269,131 @@ ecma_builtin_array_prototype_object_find (ecma_value_t predicate, /**< callback
/* 9. */
return is_find ? ECMA_VALUE_UNDEFINED : ecma_make_integer_value (-1);
} /* ecma_builtin_array_prototype_object_find */
/**
* The Array.prototype object's 'copyWithin' routine
*
* See also:
* ECMA-262 v6, 22.1.3.3
*
* @return ecma value
* Returned value must be freed with ecma_free_value.
*/
static ecma_value_t
ecma_builtin_array_prototype_object_copy_within (const ecma_value_t args[], /**< arguments list */
ecma_length_t args_number, /**< number of arguments */
ecma_object_t *obj_p, /**< array object */
uint32_t len) /**< array object's length */
{
if (args_number == 0)
{
return ecma_copy_value (ecma_make_object_value (obj_p));
}
ecma_number_t target_num;
ecma_value_t error = ecma_op_to_integer (args[0], &target_num);
if (ECMA_IS_VALUE_ERROR (error))
{
return error;
}
uint32_t target = (uint32_t) (ecma_number_is_negative (target_num) ? JERRY_MAX (len + target_num, 0) :
JERRY_MIN (target_num, len));
uint32_t start = 0;
uint32_t end = len;
if (args_number > 1)
{
ecma_number_t start_num;
error = ecma_op_to_integer (args[1], &start_num);
if (ECMA_IS_VALUE_ERROR (error))
{
return error;
}
start = (uint32_t) (ecma_number_is_negative (start_num) ? JERRY_MAX (len + start_num, 0) :
JERRY_MIN (start_num, len));
if (args_number > 2)
{
if (ecma_is_value_undefined (args[2]))
{
end = len;
}
else
{
ecma_number_t end_num;
error = ecma_op_to_integer (args[2], &end_num);
if (ECMA_IS_VALUE_ERROR (error))
{
return error;
}
end = (uint32_t) (ecma_number_is_negative (end_num) ? JERRY_MAX (len + end_num, 0) :
JERRY_MIN (end_num, len));
}
}
}
ecma_free_value (error);
uint32_t count = JERRY_MIN (end - start, len - target);
bool forward = true;
if (start < target && target < start + count)
{
start = start + count - 1;
target = target + count - 1;
forward = false;
}
while (count > 0)
{
ecma_value_t get_value = ecma_op_object_find_by_uint32_index (obj_p, start);
if (ECMA_IS_VALUE_ERROR (get_value))
{
return get_value;
}
ecma_value_t op_value;
if (ecma_is_value_found (get_value))
{
op_value = ecma_op_object_put_by_uint32_index (obj_p, target, get_value, true);
}
else
{
op_value = ecma_op_object_delete_by_uint32_index (obj_p, target, true);
}
ecma_free_value (get_value);
if (ECMA_IS_VALUE_ERROR (op_value))
{
return op_value;
}
ecma_free_value (op_value);
if (forward)
{
start++;
target++;
}
else
{
start--;
target--;
}
count--;
}
return ecma_copy_value (ecma_make_object_value (obj_p));
} /* ecma_builtin_array_prototype_object_copy_within */
#endif /* ENABLED (JERRY_ES2015_BUILTIN) */
#if ENABLED (JERRY_ES2015_BUILTIN_ITERATOR)
@@ -2498,6 +2624,14 @@ ecma_builtin_array_prototype_dispatch_routine (uint16_t builtin_routine_id, /**<
break;
}
#if ENABLED (JERRY_ES2015_BUILTIN)
case ECMA_ARRAY_PROTOTYPE_COPY_WITHIN:
{
ret_value = ecma_builtin_array_prototype_object_copy_within (arguments_list_p,
arguments_number,
obj_p,
length);
break;
}
case ECMA_ARRAY_PROTOTYPE_FIND:
case ECMA_ARRAY_PROTOTYPE_FIND_INDEX:
{
@@ -66,6 +66,7 @@ ROUTINE (LIT_MAGIC_STRING_REDUCE_RIGHT_UL, ECMA_ARRAY_PROTOTYPE_REDUCE_RIGHT, NO
ROUTINE (LIT_MAGIC_STRING_FIND, ECMA_ARRAY_PROTOTYPE_FIND, 2, 1)
ROUTINE (LIT_MAGIC_STRING_FIND_INDEX, ECMA_ARRAY_PROTOTYPE_FIND_INDEX, 2, 1)
ROUTINE (LIT_MAGIC_STRING_FILL, ECMA_ARRAY_PROTOTYPE_FILL, 3, 1)
ROUTINE (LIT_MAGIC_STRING_COPY_WITHIN, ECMA_ARRAY_PROTOTYPE_COPY_WITHIN, NON_FIXED, 2)
#endif /* ENABLED (JERRY_ES2015_BUILTIN) */
#if ENABLED (JERRY_ES2015_BUILTIN_ITERATOR)
ROUTINE (LIT_MAGIC_STRING_ENTRIES, ECMA_ARRAY_PROTOTYPE_ENTRIES, 0, 0)
+4 -2
View File
@@ -564,7 +564,8 @@ 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)
#if ENABLED (JERRY_BUILTIN_ARRAY) && ENABLED (JERRY_ES2015_BUILTIN) \
|| 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")
@@ -832,7 +833,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)
#elif ENABLED (JERRY_BUILTIN_ARRAY) && ENABLED (JERRY_ES2015_BUILTIN) \
|| 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)