diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.c b/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.c
index 53391eae6..82532a667 100644
--- a/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.c
+++ b/jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.c
@@ -1252,6 +1252,7 @@ clean_up:
* The Array.prototype object's 'splice' routine
*
* See also:
+ * ECMA-262 v11, 22.1.3.28
* ECMA-262 v5, 15.4.4.12
*
* @return ecma value
@@ -1263,105 +1264,97 @@ ecma_builtin_array_prototype_object_splice (const ecma_value_t args[], /**< argu
ecma_object_t *obj_p, /**< object */
ecma_length_t len) /**< object's length */
{
+ ecma_length_t actual_start = 0;
+ ecma_length_t actual_delete_count = 0;
+ ecma_length_t insert_count = 0;
+
+ if (args_number > 0)
+ {
+ /* ES5.1: 6, ES11: 4. */
+ if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (args[0],
+ len,
+ &actual_start)))
+ {
+ return ECMA_VALUE_ERROR;
+ }
+
+ /* ES11: 6. */
+ if (args_number == 1)
+ {
+ actual_delete_count = len - actual_start;
+ }
+ /* ES11: 7. */
+ else
+ {
+ insert_count = args_number - 2;
+
+ ecma_number_t delete_num;
+ if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (args[1], &delete_num)))
+ {
+ return ECMA_VALUE_ERROR;
+ }
+
+ /* ES5.1: 7 */
+ actual_delete_count = (ecma_length_t) (JERRY_MIN (JERRY_MAX (delete_num, 0),
+ (ecma_number_t) (len - actual_start)));
+ }
+ }
+
+ ecma_length_t new_length = len + insert_count - actual_delete_count;
+
#if ENABLED (JERRY_ESNEXT)
- ecma_value_t new_array = ecma_op_array_species_create (obj_p, 0);
+ /* ES11: 8. */
+ if (new_length > ECMA_NUMBER_MAX_SAFE_INTEGER)
+ {
+ return ecma_raise_type_error (ECMA_ERR_MSG ("Invalid new array length"));
+ }
+
+ /* ES11: 9. */
+ ecma_value_t new_array = ecma_op_array_species_create (obj_p, actual_delete_count);
if (ECMA_IS_VALUE_ERROR (new_array))
{
return new_array;
}
#else /* !ENABLED (JERRY_ESNEXT) */
- ecma_value_t new_array = ecma_op_create_array_object (NULL, 0, false);
+ /* ES5.1: 2. */
+ ecma_value_t length = ecma_make_length_value (actual_delete_count);
+ ecma_value_t new_array = ecma_op_create_array_object (&length, 1, true);
JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (new_array));
+ ecma_free_value (length);
#endif /* ENABLED (JERRY_ESNEXT) */
ecma_object_t *new_array_p = ecma_get_object_from_value (new_array);
- ecma_length_t start = 0;
- ecma_length_t delete_count = 0;
-
- if (args_number > 0)
- {
- /* 5. 6. */
- if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (args[0],
- len,
- &start)))
- {
- ecma_deref_object (new_array_p);
- return ECMA_VALUE_ERROR;
- }
-
- /*
- * If there is only one argument, that will be the start argument,
- * and we must delete the additional elements.
- */
- if (args_number == 1)
- {
- delete_count = len - start;
- }
- else
- {
- /* 7. */
- ecma_number_t delete_num;
- if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (args[1], &delete_num)))
- {
- ecma_deref_object (new_array_p);
- return ECMA_VALUE_ERROR;
- }
-
- if (!ecma_number_is_nan (delete_num))
- {
- if (ecma_number_is_negative (delete_num))
- {
- delete_count = 0;
- }
- else
- {
- delete_count = ecma_number_is_infinity (delete_num) ? len : ecma_number_to_uint32 (delete_num);
-
- if (delete_count > len - start)
- {
- delete_count = len - start;
- }
- }
- }
- else
- {
- delete_count = 0;
- }
- }
- }
-
- /* 8-9. */
+ /* ES5.1: 8, ES11: 10. */
ecma_length_t k = 0;
- for (ecma_length_t del_item_idx; k < delete_count; k++)
+ /* ES5.1: 9, ES11: 11. */
+ for (; k < actual_delete_count; k++)
{
- /* 9.a - 9.b */
- del_item_idx = k + start;
+ ecma_length_t from = actual_start + k;
+ ecma_value_t from_present = ecma_op_object_find_by_index (obj_p, from);
- ecma_value_t get_value = ecma_op_object_find_by_index (obj_p, del_item_idx);
-
- if (ECMA_IS_VALUE_ERROR (get_value))
+ if (ECMA_IS_VALUE_ERROR (from_present))
{
ecma_deref_object (new_array_p);
- return get_value;
+ return from_present;
}
- if (ecma_is_value_found (get_value))
+ if (ecma_is_value_found (from_present))
{
- /* 9.c.ii */
- ecma_value_t put_comp;
#if ENABLED (JERRY_ESNEXT)
const uint32_t prop_flags = ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE | ECMA_IS_THROW;
#else /* !ENABLED (JERRY_ESNEXT) */
const uint32_t prop_flags = ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE;
#endif /* ENABLED (JERRY_ESNEXT) */
- put_comp = ecma_builtin_helper_def_prop_by_index (new_array_p,
- k,
- get_value,
- prop_flags);
- ecma_free_value (get_value);
+
+ ecma_value_t put_comp = ecma_builtin_helper_def_prop_by_index (new_array_p,
+ k,
+ from_present,
+ prop_flags);
+ ecma_free_value (from_present);
+
#if ENABLED (JERRY_ESNEXT)
if (ECMA_IS_VALUE_ERROR (put_comp))
{
@@ -1375,131 +1368,110 @@ ecma_builtin_array_prototype_object_splice (const ecma_value_t args[], /**< argu
}
#if ENABLED (JERRY_ESNEXT)
- ecma_value_t new_set_length_value = ecma_builtin_array_prototype_helper_set_length (new_array_p,
- ((ecma_number_t) delete_count));
+ /* ES11: 12. */
+ ecma_value_t set_length = ecma_builtin_array_prototype_helper_set_length (new_array_p,
+ ((ecma_number_t) actual_delete_count));
- if (ECMA_IS_VALUE_ERROR (new_set_length_value))
+ if (ECMA_IS_VALUE_ERROR (set_length))
{
ecma_deref_object (new_array_p);
- return new_set_length_value;
+ return set_length;
}
#endif /* ENABLED (JERRY_ESNEXT) */
- /* 11. */
- uint32_t item_count;
-
- if (args_number > 2)
+ /* ES5.1: 12, ES11: 15. */
+ if (insert_count < actual_delete_count)
{
- item_count = (uint32_t) (args_number - 2);
- }
- else
- {
- item_count = 0;
- }
-
- const ecma_length_t new_len = len - delete_count + item_count;
-
- if (item_count != delete_count)
- {
- ecma_length_t from, to;
-
- /* 12. */
- if (item_count < delete_count)
+ for (k = actual_start; k < len - actual_delete_count; k++)
{
- /* 12.b */
- for (k = start; k < (len - delete_count); k++)
+ ecma_length_t from = k + actual_delete_count;
+ ecma_length_t to = k + insert_count;
+
+ ecma_value_t from_present = ecma_op_object_find_by_index (obj_p, from);
+
+ if (ECMA_IS_VALUE_ERROR (from_present))
{
- from = k + delete_count;
- to = k + item_count;
-
- ecma_value_t get_value = ecma_op_object_find_by_index (obj_p, from);
-
- if (ECMA_IS_VALUE_ERROR (get_value))
- {
- ecma_deref_object (new_array_p);
- return get_value;
- }
-
- /* 12.b.iii */
- ecma_value_t operation_value;
- if (ecma_is_value_found (get_value))
- {
- /* 12.b.iv */
- operation_value = ecma_op_object_put_by_index (obj_p, to, get_value, true);
- ecma_free_value (get_value);
- }
- else
- {
- /* 12.b.v */
- operation_value = ecma_op_object_delete_by_index (obj_p, to, true);
- }
-
- if (ECMA_IS_VALUE_ERROR (operation_value))
- {
- ecma_deref_object (new_array_p);
- return operation_value;
- }
+ ecma_deref_object (new_array_p);
+ return from_present;
}
- /* 12.d */
- for (k = len; k > new_len; k--)
- {
- ecma_value_t del_value = ecma_op_object_delete_by_index (obj_p, k - 1, true);
+ ecma_value_t operation_value;
- if (ECMA_IS_VALUE_ERROR (del_value))
- {
- ecma_deref_object (new_array_p);
- return del_value;
- }
+ if (ecma_is_value_found (from_present))
+ {
+ operation_value = ecma_op_object_put_by_index (obj_p, to, from_present, true);
+ ecma_free_value (from_present);
+ }
+ else
+ {
+ operation_value = ecma_op_object_delete_by_index (obj_p, to, true);
+ }
+
+ if (ECMA_IS_VALUE_ERROR (operation_value))
+ {
+ ecma_deref_object (new_array_p);
+ return operation_value;
}
}
- /* 13. */
- else
+
+ k = len;
+
+ for (k = len; k > new_length; k--)
{
- JERRY_ASSERT (item_count > delete_count);
- /* 13.b */
- for (k = len - delete_count; k > start; k--)
+ ecma_value_t del_value = ecma_op_object_delete_by_index (obj_p, k - 1, true);
+
+ if (ECMA_IS_VALUE_ERROR (del_value))
{
- from = k + delete_count - 1;
- to = k + item_count - 1;
- /* 13.b.iii */
- ecma_value_t get_value = ecma_op_object_find_by_index (obj_p, from);
+ ecma_deref_object (new_array_p);
+ return del_value;
+ }
+ }
+ }
+ /* ES5.1: 13, ES11: 16. */
+ else if (insert_count > actual_delete_count)
+ {
+ for (k = len - actual_delete_count; k > actual_start; k--)
+ {
+ ecma_length_t from = k + actual_delete_count - 1;
+ ecma_length_t to = k + insert_count - 1;
- if (ECMA_IS_VALUE_ERROR (get_value))
- {
- ecma_deref_object (new_array_p);
- return get_value;
- }
+ ecma_value_t from_present = ecma_op_object_find_by_index (obj_p, from);
- ecma_value_t operation_value;
+ if (ECMA_IS_VALUE_ERROR (from_present))
+ {
+ ecma_deref_object (new_array_p);
+ return from_present;
+ }
- if (ecma_is_value_found (get_value))
- {
- /* 13.b.iv */
- operation_value = ecma_op_object_put_by_index (obj_p, to, get_value, true);
- ecma_free_value (get_value);
- }
- else
- {
- /* 13.b.v */
- operation_value = ecma_op_object_delete_by_index (obj_p, to, true);
- }
+ ecma_value_t operation_value;
- if (ECMA_IS_VALUE_ERROR (operation_value))
- {
- ecma_deref_object (new_array_p);
- return operation_value;
- }
+ if (ecma_is_value_found (from_present))
+ {
+ operation_value = ecma_op_object_put_by_index (obj_p, to, from_present, true);
+ ecma_free_value (from_present);
+ }
+ else
+ {
+ operation_value = ecma_op_object_delete_by_index (obj_p, to, true);
+ }
+
+ if (ECMA_IS_VALUE_ERROR (operation_value))
+ {
+ ecma_deref_object (new_array_p);
+ return operation_value;
}
}
}
- /* 15. */
+ /* ES5.1: 14, ES11: 17. */
+ k = actual_start;
+
+ /* ES5.1: 15, ES11: 18. */
uint32_t idx = 0;
for (uint32_t arg_index = 2; arg_index < args_number; arg_index++, idx++)
{
ecma_value_t put_value = ecma_op_object_put_by_index (obj_p,
- start + idx,
+ actual_start + idx,
args[arg_index],
true);
@@ -1510,15 +1482,16 @@ ecma_builtin_array_prototype_object_splice (const ecma_value_t args[], /**< argu
}
}
- /* 16. */
- ecma_value_t set_length_value = ecma_builtin_array_prototype_helper_set_length (obj_p, ((ecma_number_t) new_len));
+ /* ES5.1: 16, ES11: 19. */
+ ecma_value_t set_new_length = ecma_builtin_array_prototype_helper_set_length (obj_p, ((ecma_number_t) new_length));
- if (ECMA_IS_VALUE_ERROR (set_length_value))
+ if (ECMA_IS_VALUE_ERROR (set_new_length))
{
ecma_deref_object (new_array_p);
- return set_length_value;
+ return set_new_length;
}
+ /* ES5.1: 17, ES11: 20. */
return new_array;
} /* ecma_builtin_array_prototype_object_splice */
diff --git a/tests/test262-esnext-excludelist.xml b/tests/test262-esnext-excludelist.xml
index a7aab840b..7042e2cb9 100644
--- a/tests/test262-esnext-excludelist.xml
+++ b/tests/test262-esnext-excludelist.xml
@@ -151,14 +151,9 @@
-
-
-
-
-