Fix the indexing of Array builtin functions.
The index-dependant builtins didn't handle correctly the positive Infinity value. JerryScript-DCO-1.0-Signed-off-by: Zsolt Borbély zsborbely.u-szeged@partner.samsung.com
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
/* Copyright 2014-2015 Samsung Electronics Co., Ltd.
|
/* Copyright 2014-2015 Samsung Electronics Co., Ltd.
|
||||||
|
* Copyright 2015 University of Szeged.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -892,46 +893,20 @@ ecma_builtin_array_prototype_object_index_of (ecma_value_t this_arg, /**< this a
|
|||||||
/* 5. */
|
/* 5. */
|
||||||
ECMA_OP_TO_NUMBER_TRY_CATCH (arg_from_idx, arg2, ret_value);
|
ECMA_OP_TO_NUMBER_TRY_CATCH (arg_from_idx, arg2, ret_value);
|
||||||
|
|
||||||
int32_t from_idx_int = ecma_number_to_int32 (arg_from_idx);
|
uint32_t from_idx = ecma_builtin_helper_array_index_normalize (arg_from_idx, len);
|
||||||
|
|
||||||
/* 6. */
|
/* 6. */
|
||||||
if (from_idx_int > 0 && (uint32_t) from_idx_int >= len)
|
if (from_idx >= len)
|
||||||
{
|
{
|
||||||
ret_value = ecma_make_normal_completion_value (ecma_make_number_value (num_p));
|
ret_value = ecma_make_normal_completion_value (ecma_make_number_value (num_p));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint32_t k;
|
JERRY_ASSERT (from_idx < len);
|
||||||
|
|
||||||
/* 7 */
|
for (; from_idx < len && *num_p < 0 && ecma_is_completion_value_empty (ret_value); from_idx++)
|
||||||
if (from_idx_int >= 0)
|
|
||||||
{
|
{
|
||||||
k = (uint32_t) from_idx_int;
|
ecma_string_t *idx_str_p = ecma_new_ecma_string_from_uint32 (from_idx);
|
||||||
}
|
|
||||||
/* 8. */
|
|
||||||
else
|
|
||||||
{
|
|
||||||
from_idx_int = -from_idx_int;
|
|
||||||
|
|
||||||
/* As opposed to the standard, we prevent k from being negative, so that we can use an uint32 */
|
|
||||||
if ((uint32_t) from_idx_int < len)
|
|
||||||
{
|
|
||||||
/* 8.a */
|
|
||||||
k = len - (uint32_t) from_idx_int;
|
|
||||||
}
|
|
||||||
/* If k would've been negative */
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* 8.b */
|
|
||||||
k = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
JERRY_ASSERT (k < len);
|
|
||||||
|
|
||||||
for (; k < len && *num_p < 0 && ecma_is_completion_value_empty (ret_value); k++)
|
|
||||||
{
|
|
||||||
ecma_string_t *idx_str_p = ecma_new_ecma_string_from_uint32 (k);
|
|
||||||
|
|
||||||
/* 9.a */
|
/* 9.a */
|
||||||
if (ecma_op_object_get_property (obj_p, idx_str_p) != NULL)
|
if (ecma_op_object_get_property (obj_p, idx_str_p) != NULL)
|
||||||
@@ -942,7 +917,7 @@ ecma_builtin_array_prototype_object_index_of (ecma_value_t this_arg, /**< this a
|
|||||||
/* 9.b.ii */
|
/* 9.b.ii */
|
||||||
if (ecma_op_strict_equality_compare (arg1, get_value))
|
if (ecma_op_strict_equality_compare (arg1, get_value))
|
||||||
{
|
{
|
||||||
*num_p = ecma_uint32_to_number (k);
|
*num_p = ecma_uint32_to_number (from_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ECMA_FINALIZE (get_value);
|
ECMA_FINALIZE (get_value);
|
||||||
@@ -1019,59 +994,75 @@ ecma_builtin_array_prototype_object_last_index_of (ecma_value_t this_arg, /**< t
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint32_t k = len - 1;
|
uint32_t from_idx = len - 1;
|
||||||
|
|
||||||
/* 5. */
|
/* 5. */
|
||||||
if (!ecma_is_value_undefined (arg2))
|
if (!ecma_is_value_undefined (arg2))
|
||||||
{
|
{
|
||||||
ECMA_OP_TO_NUMBER_TRY_CATCH (arg_from_idx, arg2, ret_value);
|
ECMA_OP_TO_NUMBER_TRY_CATCH (arg_from_idx, arg2, ret_value);
|
||||||
int32_t n = ecma_number_to_int32 (arg_from_idx);
|
|
||||||
|
|
||||||
/* 6. */
|
if (!ecma_number_is_nan (arg_from_idx))
|
||||||
if (n >= 0)
|
|
||||||
{
|
{
|
||||||
/* min(n, len - 1)*/
|
|
||||||
if ((uint32_t) n > len - 1)
|
if (ecma_number_is_infinity (arg_from_idx))
|
||||||
{
|
{
|
||||||
k = len - 1;
|
from_idx = ecma_number_is_negative (arg_from_idx) ? (uint32_t) -1 : len - 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
k = (uint32_t) n;
|
int32_t int_from_idx = ecma_number_to_int32 (arg_from_idx);
|
||||||
|
|
||||||
|
/* 6. */
|
||||||
|
if (int_from_idx >= 0)
|
||||||
|
{
|
||||||
|
/* min(int_from_idx, len - 1)*/
|
||||||
|
if ((uint32_t) int_from_idx > len - 1)
|
||||||
|
{
|
||||||
|
from_idx = len - 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
from_idx = (uint32_t) int_from_idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* 7. */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int_from_idx = -int_from_idx;
|
||||||
|
|
||||||
|
/* We prevent from_idx from being negative, so that we can use an uint32 */
|
||||||
|
if ((uint32_t) int_from_idx <= len)
|
||||||
|
{
|
||||||
|
from_idx = len - (uint32_t) int_from_idx;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* If from_idx would be negative, we set it to UINT_MAX. See reasoning for this in the comment
|
||||||
|
* at the for loop below.
|
||||||
|
*/
|
||||||
|
from_idx = (uint32_t) -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* 7. */
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
n = -n;
|
from_idx = 0;
|
||||||
|
|
||||||
/* We prevent k from being negative, so that we can use an uint32 */
|
|
||||||
if ((uint32_t) n <= len)
|
|
||||||
{
|
|
||||||
k = len - (uint32_t) n;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* If k would be negative, we set it to UINT_MAX. See reasoning for this in the comment
|
|
||||||
* at the for loop below.
|
|
||||||
*/
|
|
||||||
k = (uint32_t) -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ECMA_OP_TO_NUMBER_FINALIZE (arg_from_idx);
|
ECMA_OP_TO_NUMBER_FINALIZE (arg_from_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 8.
|
/* 8.
|
||||||
* We should break from the loop when k < 0. We can still use an uint32_t for k, and check
|
* We should break from the loop when from_idx < 0. We can still use an uint32_t for from_idx, and check
|
||||||
* for an underflow instead. This is safe, because k will always start in [0, len - 1],
|
* for an underflow instead. This is safe, because from_idx will always start in [0, len - 1],
|
||||||
* and len is in [0, UINT_MAX], so k >= len means we've had an underflow, and should stop.
|
* and len is in [0, UINT_MAX], so from_idx >= len means we've had an underflow, and should stop.
|
||||||
*/
|
*/
|
||||||
for (;k < len && *num_p < 0 && ecma_is_completion_value_empty (ret_value); k--)
|
for (; from_idx < len && *num_p < 0 && ecma_is_completion_value_empty (ret_value); from_idx--)
|
||||||
{
|
{
|
||||||
/* 8.a */
|
/* 8.a */
|
||||||
ecma_string_t *idx_str_p = ecma_new_ecma_string_from_uint32 (k);
|
ecma_string_t *idx_str_p = ecma_new_ecma_string_from_uint32 (from_idx);
|
||||||
|
|
||||||
/* 8.a */
|
/* 8.a */
|
||||||
if (ecma_op_object_get_property (obj_p, idx_str_p) != NULL)
|
if (ecma_op_object_get_property (obj_p, idx_str_p) != NULL)
|
||||||
@@ -1082,7 +1073,7 @@ ecma_builtin_array_prototype_object_last_index_of (ecma_value_t this_arg, /**< t
|
|||||||
/* 8.b.ii */
|
/* 8.b.ii */
|
||||||
if (ecma_op_strict_equality_compare (arg1, get_value))
|
if (ecma_op_strict_equality_compare (arg1, get_value))
|
||||||
{
|
{
|
||||||
*num_p = ecma_uint32_to_number (k);
|
*num_p = ecma_uint32_to_number (from_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ECMA_FINALIZE (get_value);
|
ECMA_FINALIZE (get_value);
|
||||||
@@ -2029,30 +2020,8 @@ ecma_builtin_array_prototype_object_slice (ecma_value_t this_arg, /**< 'this' ar
|
|||||||
|
|
||||||
/* 5. */
|
/* 5. */
|
||||||
ECMA_OP_TO_NUMBER_TRY_CATCH (start_num, arg1, ret_value);
|
ECMA_OP_TO_NUMBER_TRY_CATCH (start_num, arg1, ret_value);
|
||||||
int32_t relative_start = ecma_number_to_int32 (start_num);
|
|
||||||
|
|
||||||
/* 6. */
|
start = ecma_builtin_helper_array_index_normalize (start_num, len);
|
||||||
if (relative_start < 0)
|
|
||||||
{
|
|
||||||
uint32_t start_abs = (uint32_t) -relative_start;
|
|
||||||
|
|
||||||
if (start_abs > len)
|
|
||||||
{
|
|
||||||
start = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
start = len - start_abs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
start = (uint32_t) relative_start;
|
|
||||||
if (start > len)
|
|
||||||
{
|
|
||||||
start = len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 7. */
|
/* 7. */
|
||||||
if (ecma_is_value_undefined (arg2))
|
if (ecma_is_value_undefined (arg2))
|
||||||
@@ -2062,30 +2031,9 @@ ecma_builtin_array_prototype_object_slice (ecma_value_t this_arg, /**< 'this' ar
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* 7. part 2*/
|
/* 7. part 2*/
|
||||||
ECMA_OP_TO_NUMBER_TRY_CATCH (end_num, arg2, ret_value)
|
ECMA_OP_TO_NUMBER_TRY_CATCH (end_num, arg2, ret_value);
|
||||||
int32_t relative_end = ecma_number_to_int32 (end_num);
|
|
||||||
|
|
||||||
if (relative_end < 0)
|
end = ecma_builtin_helper_array_index_normalize (end_num, len);
|
||||||
{
|
|
||||||
uint32_t end_abs = (uint32_t) -relative_end;
|
|
||||||
|
|
||||||
if (end_abs > len)
|
|
||||||
{
|
|
||||||
end = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
end = len - end_abs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
end = (uint32_t) relative_end;
|
|
||||||
if (end > len)
|
|
||||||
{
|
|
||||||
end = len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ECMA_OP_TO_NUMBER_FINALIZE (end_num);
|
ECMA_OP_TO_NUMBER_FINALIZE (end_num);
|
||||||
}
|
}
|
||||||
@@ -2197,29 +2145,7 @@ ecma_builtin_array_prototype_object_splice (ecma_value_t this_arg, /**< this arg
|
|||||||
args[0],
|
args[0],
|
||||||
ret_value);
|
ret_value);
|
||||||
|
|
||||||
int32_t relative_start = ecma_number_to_int32 (start_num);
|
start = ecma_builtin_helper_array_index_normalize (start_num, len);
|
||||||
|
|
||||||
/* 6. */
|
|
||||||
if (relative_start < 0)
|
|
||||||
{
|
|
||||||
uint32_t start_abs = (uint32_t) - relative_start;
|
|
||||||
if (start_abs > len)
|
|
||||||
{
|
|
||||||
start = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
start = len - start_abs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
start = (uint32_t) relative_start;
|
|
||||||
if (start > len)
|
|
||||||
{
|
|
||||||
start = len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If there is only one argument, that will be the start argument,
|
* If there is only one argument, that will be the start argument,
|
||||||
@@ -2236,22 +2162,22 @@ ecma_builtin_array_prototype_object_splice (ecma_value_t this_arg, /**< this arg
|
|||||||
args[1],
|
args[1],
|
||||||
ret_value);
|
ret_value);
|
||||||
|
|
||||||
int32_t delete_count_int = ecma_number_to_int32 (delete_num);
|
if (!ecma_number_is_nan (delete_num))
|
||||||
|
|
||||||
if (delete_count_int > 0)
|
|
||||||
{
|
{
|
||||||
delete_count = (uint32_t) delete_count_int;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
delete_count = 0;
|
delete_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len - start < delete_count)
|
|
||||||
{
|
|
||||||
delete_count = len - start;
|
|
||||||
}
|
|
||||||
|
|
||||||
ECMA_OP_TO_NUMBER_FINALIZE (delete_num);
|
ECMA_OP_TO_NUMBER_FINALIZE (delete_num);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -270,6 +270,69 @@ ecma_builtin_helper_object_get_properties (ecma_object_t *obj_p, /** < object */
|
|||||||
return new_array;
|
return new_array;
|
||||||
} /* ecma_builtin_helper_object_get_properties */
|
} /* ecma_builtin_helper_object_get_properties */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to normalizing an array index
|
||||||
|
*
|
||||||
|
* This function clamps the given index to the [0, length] range.
|
||||||
|
* If the index is negative, it is used as the offset from the end of the array,
|
||||||
|
* to compute normalized index.
|
||||||
|
* If the index is greater than the length of the array, the normalized index will be the length of the array.
|
||||||
|
*
|
||||||
|
* See also:
|
||||||
|
* ECMA-262 v5, 15.4.4.10 steps 5-6, 7 (part 2) and 8
|
||||||
|
* ECMA-262 v5, 15.4.4.12 steps 5-6
|
||||||
|
* ECMA-262 v5, 15.4.4.14 steps 5
|
||||||
|
* ECMA-262 v5, 15.5.4.13 steps 4, 5 (part 2) and 6-7
|
||||||
|
*
|
||||||
|
* Used by:
|
||||||
|
* - The Array.prototype.slice routine.
|
||||||
|
* - The Array.prototype.splice routine.
|
||||||
|
* - The Array.prototype.indexOf routine.
|
||||||
|
* - The String.prototype.slice routine.
|
||||||
|
*
|
||||||
|
* @return uint32_t - the normalized value of the index
|
||||||
|
*/
|
||||||
|
uint32_t
|
||||||
|
ecma_builtin_helper_array_index_normalize (ecma_number_t index, /**< index */
|
||||||
|
uint32_t length) /**< array's length */
|
||||||
|
{
|
||||||
|
uint32_t norm_index;
|
||||||
|
|
||||||
|
if (!ecma_number_is_nan (index))
|
||||||
|
{
|
||||||
|
|
||||||
|
if (ecma_number_is_infinity (index))
|
||||||
|
{
|
||||||
|
norm_index = ecma_number_is_negative (index) ? 0 : length;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const int32_t int_index = ecma_number_to_int32 (index);
|
||||||
|
|
||||||
|
if (int_index < 0)
|
||||||
|
{
|
||||||
|
const uint32_t uint_index = (uint32_t) - int_index;
|
||||||
|
norm_index = uint_index > length ? 0 : length - uint_index;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
norm_index = (uint32_t) int_index;
|
||||||
|
|
||||||
|
if (norm_index > length)
|
||||||
|
{
|
||||||
|
norm_index = length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
norm_index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return norm_index;
|
||||||
|
} /* ecma_builtin_helper_array_index_normalize */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
* @}
|
* @}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ extern ecma_completion_value_t ecma_builtin_helper_object_to_string (const ecma_
|
|||||||
extern ecma_completion_value_t ecma_builtin_helper_get_to_locale_string_at_index (ecma_object_t *obj_p, uint32_t index);
|
extern ecma_completion_value_t ecma_builtin_helper_get_to_locale_string_at_index (ecma_object_t *obj_p, uint32_t index);
|
||||||
extern ecma_completion_value_t ecma_builtin_helper_object_get_properties (ecma_object_t *obj,
|
extern ecma_completion_value_t ecma_builtin_helper_object_get_properties (ecma_object_t *obj,
|
||||||
bool only_enumerable_properties);
|
bool only_enumerable_properties);
|
||||||
|
extern uint32_t ecma_builtin_helper_array_index_normalize (ecma_number_t index, uint32_t length);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ecma-alloc.h"
|
#include "ecma-alloc.h"
|
||||||
|
#include "ecma-builtin-helpers.h"
|
||||||
#include "ecma-builtins.h"
|
#include "ecma-builtins.h"
|
||||||
#include "ecma-conversion.h"
|
#include "ecma-conversion.h"
|
||||||
#include "ecma-exceptions.h"
|
#include "ecma-exceptions.h"
|
||||||
@@ -332,46 +333,16 @@ ecma_builtin_string_prototype_object_slice (ecma_value_t this_arg, /**< this arg
|
|||||||
|
|
||||||
const uint32_t len = (uint32_t) ecma_string_get_length (get_string_val);
|
const uint32_t len = (uint32_t) ecma_string_get_length (get_string_val);
|
||||||
|
|
||||||
/* 4. */
|
/* 4. 6. */
|
||||||
uint32_t start = 0, end = len;
|
uint32_t start = 0, end = len;
|
||||||
|
|
||||||
ECMA_OP_TO_NUMBER_TRY_CATCH (start_num,
|
ECMA_OP_TO_NUMBER_TRY_CATCH (start_num,
|
||||||
arg1,
|
arg1,
|
||||||
ret_value);
|
ret_value);
|
||||||
|
|
||||||
if (!ecma_number_is_nan (start_num))
|
start = ecma_builtin_helper_array_index_normalize (start_num, len);
|
||||||
{
|
|
||||||
|
|
||||||
if (ecma_number_is_infinity (start_num))
|
/* 5. 7. */
|
||||||
{
|
|
||||||
start = ecma_number_is_negative (start_num) ? 0 : len;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const int int_start = ecma_number_to_int32 (start_num);
|
|
||||||
|
|
||||||
if (int_start < 0)
|
|
||||||
{
|
|
||||||
const uint32_t start_abs = (uint32_t) - int_start;
|
|
||||||
start = start_abs > len ? 0 : len - start_abs;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
start = (uint32_t) int_start;
|
|
||||||
|
|
||||||
if (start > len)
|
|
||||||
{
|
|
||||||
start = len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
start = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 5. */
|
|
||||||
if (ecma_is_value_undefined (arg2))
|
if (ecma_is_value_undefined (arg2))
|
||||||
{
|
{
|
||||||
end = len;
|
end = len;
|
||||||
@@ -382,37 +353,7 @@ ecma_builtin_string_prototype_object_slice (ecma_value_t this_arg, /**< this arg
|
|||||||
arg2,
|
arg2,
|
||||||
ret_value);
|
ret_value);
|
||||||
|
|
||||||
if (!ecma_number_is_nan (end_num))
|
end = ecma_builtin_helper_array_index_normalize (end_num, len);
|
||||||
{
|
|
||||||
|
|
||||||
if (ecma_number_is_infinity (end_num))
|
|
||||||
{
|
|
||||||
end = ecma_number_is_negative (end_num) ? 0 : len;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const int32_t int_end = ecma_number_to_int32 (end_num);
|
|
||||||
|
|
||||||
if (int_end < 0)
|
|
||||||
{
|
|
||||||
const uint32_t end_abs = (uint32_t) - int_end;
|
|
||||||
end = end_abs > len ? 0 : len - end_abs;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
end = (uint32_t) int_end;
|
|
||||||
|
|
||||||
if (end > len)
|
|
||||||
{
|
|
||||||
end = len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
end = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ECMA_OP_TO_NUMBER_FINALIZE (end_num);
|
ECMA_OP_TO_NUMBER_FINALIZE (end_num);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,10 @@ var index = array.indexOf(obj);
|
|||||||
assert(index === 3);
|
assert(index === 3);
|
||||||
assert(array[index] === obj);
|
assert(array[index] === obj);
|
||||||
|
|
||||||
|
assert(array.indexOf("foo", NaN) === 0);
|
||||||
|
assert(array.indexOf("foo", Infinity) === -1);
|
||||||
|
assert(array.indexOf("foo", -Infinity) === 0);
|
||||||
|
|
||||||
// Checking behavior when length is zero
|
// Checking behavior when length is zero
|
||||||
var obj = { indexOf : Array.prototype.indexOf, length : 0 };
|
var obj = { indexOf : Array.prototype.indexOf, length : 0 };
|
||||||
assert(obj.indexOf("foo") === -1);
|
assert(obj.indexOf("foo") === -1);
|
||||||
|
|||||||
@@ -33,6 +33,10 @@ var index = array.lastIndexOf(obj);
|
|||||||
assert(index === 3);
|
assert(index === 3);
|
||||||
assert(array[index] === obj);
|
assert(array[index] === obj);
|
||||||
|
|
||||||
|
assert(array.lastIndexOf("foo", NaN) === 0);
|
||||||
|
assert(array.lastIndexOf("foo", Infinity) === 4);
|
||||||
|
assert(array.lastIndexOf("foo", -Infinity) === -1);
|
||||||
|
|
||||||
var arr = [];
|
var arr = [];
|
||||||
arr[4294967294] = "foo";
|
arr[4294967294] = "foo";
|
||||||
assert(arr.lastIndexOf("foo", -1) === 4294967294)
|
assert(arr.lastIndexOf("foo", -1) === 4294967294)
|
||||||
|
|||||||
@@ -20,6 +20,9 @@ var array2 = array.slice("a", "3");
|
|||||||
var array3 = array.slice(-2);
|
var array3 = array.slice(-2);
|
||||||
var array4 = array.slice(-12, undefined);
|
var array4 = array.slice(-12, undefined);
|
||||||
var array5 = array.slice(undefined, -3);
|
var array5 = array.slice(undefined, -3);
|
||||||
|
var array6 = array.slice(Infinity, NaN);
|
||||||
|
var array7 = array.slice(-Infinity, Infinity);
|
||||||
|
var array8 = array.slice(NaN, -Infinity);
|
||||||
|
|
||||||
assert (array1.length == 4);
|
assert (array1.length == 4);
|
||||||
assert (array1[0] == 54);
|
assert (array1[0] == 54);
|
||||||
@@ -45,6 +48,16 @@ assert (array4[3] == -127);
|
|||||||
assert (array5.length == 1);
|
assert (array5.length == 1);
|
||||||
assert (array5[0] == 54);
|
assert (array5[0] == 54);
|
||||||
|
|
||||||
|
assert (array6.length == 0);
|
||||||
|
|
||||||
|
assert (array7.length == 4);
|
||||||
|
assert (array7[0] == 54);
|
||||||
|
assert (array7[1] == undefined);
|
||||||
|
assert (array7[2] == "Lemon");
|
||||||
|
assert (array7[3] == -127);
|
||||||
|
|
||||||
|
assert (array8.length == 0);
|
||||||
|
|
||||||
// Checking behavior when unable to get length
|
// Checking behavior when unable to get length
|
||||||
var obj = { slice : Array.prototype.slice };
|
var obj = { slice : Array.prototype.slice };
|
||||||
Object.defineProperty(obj, 'length', { 'get' : function () { throw new ReferenceError ("foo"); } });
|
Object.defineProperty(obj, 'length', { 'get' : function () { throw new ReferenceError ("foo"); } });
|
||||||
|
|||||||
@@ -88,6 +88,37 @@ assert (array[3] == -127);
|
|||||||
assert (array[4] == "sunshine");
|
assert (array[4] == "sunshine");
|
||||||
assert (array6.length == 0);
|
assert (array6.length == 0);
|
||||||
|
|
||||||
|
// --------------------------------------------------------
|
||||||
|
array = setDefaultValues();
|
||||||
|
var array7 = array.splice(Infinity, NaN);
|
||||||
|
assert (array.length == 4);
|
||||||
|
assert (array[0] == 54);
|
||||||
|
assert (array[1] == undefined);
|
||||||
|
assert (array[2] == -127);
|
||||||
|
assert (array[3] == "sunshine");
|
||||||
|
assert (array7.length == 0);
|
||||||
|
|
||||||
|
// --------------------------------------------------------
|
||||||
|
array = setDefaultValues();
|
||||||
|
var array8 = array.splice(-Infinity, Infinity);
|
||||||
|
|
||||||
|
assert (array.length == 0);
|
||||||
|
assert (array8.length == 4);
|
||||||
|
assert (array8[0] == 54);
|
||||||
|
assert (array8[1] == undefined);
|
||||||
|
assert (array8[2] == -127);
|
||||||
|
assert (array8[3] == "sunshine");
|
||||||
|
|
||||||
|
// --------------------------------------------------------
|
||||||
|
array = setDefaultValues();
|
||||||
|
var array9 = array.splice(NaN, -Infinity);
|
||||||
|
assert (array.length == 4);
|
||||||
|
assert (array[0] == 54);
|
||||||
|
assert (array[1] == undefined);
|
||||||
|
assert (array[2] == -127);
|
||||||
|
assert (array[3] == "sunshine");
|
||||||
|
assert (array9.length == 0);
|
||||||
|
|
||||||
// Checking behavior when unable to get length
|
// Checking behavior when unable to get length
|
||||||
var obj = {splice : Array.prototype.splice};
|
var obj = {splice : Array.prototype.splice};
|
||||||
Object.defineProperty(obj, 'length', { 'get' : function () { throw new ReferenceError ("foo"); } });
|
Object.defineProperty(obj, 'length', { 'get' : function () { throw new ReferenceError ("foo"); } });
|
||||||
|
|||||||
Reference in New Issue
Block a user