Refactor code to use ToInteger (#3224)

Fixes #3325
Fixes #3237

JerryScript-DCO-1.0-Signed-off-by: Daniella Barsony bella@inf.u-szeged.hu
This commit is contained in:
Daniella Barsony
2019-12-09 12:07:26 +01:00
committed by Robert Fancsik
parent 5ceffd209e
commit 89db9253c8
15 changed files with 399 additions and 409 deletions
@@ -801,16 +801,14 @@ ecma_builtin_array_prototype_object_slice (ecma_value_t arg1, /**< start */
{ {
uint32_t start = 0, end = len; uint32_t start = 0, end = len;
/* 5. */ /* 5. 6.*/
ecma_number_t start_num; if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (arg1,
len,
if (ECMA_IS_VALUE_ERROR (ecma_get_number (arg1, &start_num))) &start)))
{ {
return ECMA_VALUE_ERROR; return ECMA_VALUE_ERROR;
} }
start = ecma_builtin_helper_array_index_normalize (start_num, len, false);
/* 7. */ /* 7. */
if (ecma_is_value_undefined (arg2)) if (ecma_is_value_undefined (arg2))
{ {
@@ -818,15 +816,13 @@ ecma_builtin_array_prototype_object_slice (ecma_value_t arg1, /**< start */
} }
else else
{ {
/* 7. part 2 */ /* 7. part 2, 8.*/
ecma_number_t end_num; if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (arg2,
len,
if (ECMA_IS_VALUE_ERROR (ecma_get_number (arg2, &end_num))) &end)))
{ {
return ECMA_VALUE_ERROR; return ECMA_VALUE_ERROR;
} }
end = ecma_builtin_helper_array_index_normalize (end_num, len, false);
} }
JERRY_ASSERT (start <= len && end <= len); JERRY_ASSERT (start <= len && end <= len);
@@ -1189,16 +1185,15 @@ ecma_builtin_array_prototype_object_splice (const ecma_value_t args[], /**< argu
if (args_number > 0) if (args_number > 0)
{ {
/* 5. */ /* 5. 6. */
ecma_number_t start_num; if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (args[0],
if (ECMA_IS_VALUE_ERROR (ecma_get_number (args[0], &start_num))) len,
&start)))
{ {
ecma_deref_object (new_array_p); ecma_deref_object (new_array_p);
return ECMA_VALUE_ERROR; return ECMA_VALUE_ERROR;
} }
start = ecma_builtin_helper_array_index_normalize (start_num, len, false);
/* /*
* If there is only one argument, that will be the start argument, * If there is only one argument, that will be the start argument,
* and we must delete the additional elements. * and we must delete the additional elements.
@@ -1211,7 +1206,7 @@ ecma_builtin_array_prototype_object_splice (const ecma_value_t args[], /**< argu
{ {
/* 7. */ /* 7. */
ecma_number_t delete_num; ecma_number_t delete_num;
if (ECMA_IS_VALUE_ERROR (ecma_get_number (args[1], &delete_num))) if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (args[1], &delete_num)))
{ {
ecma_deref_object (new_array_p); ecma_deref_object (new_array_p);
return ECMA_VALUE_ERROR; return ECMA_VALUE_ERROR;
@@ -1525,8 +1520,8 @@ ecma_builtin_array_prototype_object_unshift (const ecma_value_t args[], /**< arg
* Returned value must be freed with ecma_free_value. * Returned value must be freed with ecma_free_value.
*/ */
static ecma_value_t static ecma_value_t
ecma_builtin_array_prototype_object_index_of (ecma_value_t arg1, /**< searchElement */ ecma_builtin_array_prototype_object_index_of (const ecma_value_t args[], /**< arguments list */
ecma_value_t arg2, /**< fromIndex */ ecma_length_t args_number, /**< number of arguments */
ecma_object_t *obj_p, /**< array object */ ecma_object_t *obj_p, /**< array object */
uint32_t len) /**< array object's length */ uint32_t len) /**< array object's length */
{ {
@@ -1537,14 +1532,32 @@ ecma_builtin_array_prototype_object_index_of (ecma_value_t arg1, /**< searchElem
} }
/* 5. */ /* 5. */
ecma_number_t arg_from_idx; ecma_number_t idx = 0;
if (args_number > 1)
if (ECMA_IS_VALUE_ERROR (ecma_get_number (arg2, &arg_from_idx)))
{ {
return ECMA_VALUE_ERROR; if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (args[1], &idx)))
{
return ECMA_VALUE_ERROR;
}
} }
uint32_t from_idx = ecma_builtin_helper_array_index_normalize (arg_from_idx, len, false); /* 6. */
if (idx >= len)
{
return ecma_make_number_value (-1);
}
/* 7. */
ecma_number_t from_idx_num = idx;
/* 8. */
if (idx < 0)
{
from_idx_num = JERRY_MAX ((ecma_number_t) len + idx, 0);
}
JERRY_ASSERT (from_idx_num >= 0 && from_idx_num <= UINT32_MAX);
uint32_t from_idx = (uint32_t) from_idx_num;
if (ecma_op_object_is_fast_array (obj_p)) if (ecma_op_object_is_fast_array (obj_p))
{ {
@@ -1557,7 +1570,7 @@ ecma_builtin_array_prototype_object_index_of (ecma_value_t arg1, /**< searchElem
while (from_idx < len) while (from_idx < len)
{ {
if (ecma_op_strict_equality_compare (arg1, buffer_p[from_idx])) if (ecma_op_strict_equality_compare (args[0], buffer_p[from_idx]))
{ {
return ecma_make_uint32_value (from_idx); return ecma_make_uint32_value (from_idx);
} }
@@ -1569,6 +1582,7 @@ ecma_builtin_array_prototype_object_index_of (ecma_value_t arg1, /**< searchElem
} }
} }
/* 6. */
while (from_idx < len) while (from_idx < len)
{ {
/* 9.a */ /* 9.a */
@@ -1581,7 +1595,7 @@ ecma_builtin_array_prototype_object_index_of (ecma_value_t arg1, /**< searchElem
/* 9.b.i, 9.b.ii */ /* 9.b.i, 9.b.ii */
if (ecma_is_value_found (get_value) if (ecma_is_value_found (get_value)
&& ecma_op_strict_equality_compare (arg1, get_value)) && ecma_op_strict_equality_compare (args[0], get_value))
{ {
ecma_free_value (get_value); ecma_free_value (get_value);
return ecma_make_uint32_value (from_idx); return ecma_make_uint32_value (from_idx);
@@ -1616,17 +1630,31 @@ ecma_builtin_array_prototype_object_last_index_of (const ecma_value_t args[], /*
return ecma_make_integer_value (-1); return ecma_make_integer_value (-1);
} }
uint32_t from_idx = len - 1; /* 5. */
ecma_number_t idx = (ecma_number_t) len - 1;
if (args_number > 1) if (args_number > 1)
{ {
ecma_number_t arg_from_idx; if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (args[1], &idx)))
if (ECMA_IS_VALUE_ERROR (ecma_get_number (args[1], &arg_from_idx)))
{ {
return ECMA_VALUE_ERROR; return ECMA_VALUE_ERROR;
} }
}
from_idx = ecma_builtin_helper_array_index_normalize (arg_from_idx, len, true); uint32_t from_idx;
/* 6 */
if (idx >= 0)
{
from_idx = (uint32_t) (JERRY_MIN (idx, len - 1));
}
else
{
ecma_number_t k = len + idx;
if (k < 0)
{
return ecma_make_integer_value (-1);
}
from_idx = (uint32_t) k;
} }
ecma_value_t search_element = (args_number > 0) ? args[0] : ECMA_VALUE_UNDEFINED; ecma_value_t search_element = (args_number > 0) ? args[0] : ECMA_VALUE_UNDEFINED;
@@ -1646,19 +1674,13 @@ ecma_builtin_array_prototype_object_last_index_of (const ecma_value_t args[], /*
{ {
return ecma_make_uint32_value (from_idx); return ecma_make_uint32_value (from_idx);
} }
from_idx--; from_idx--;
} }
return ecma_make_integer_value (-1); return ecma_make_integer_value (-1);
} }
} }
/* 8. /* 8. */
* 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 from_idx will always start in [0, len - 1],
* and len is in [0, UINT_MAX], so from_idx >= len means we've had an underflow, and should stop.
*/
while (from_idx < len) while (from_idx < len)
{ {
/* 8.a */ /* 8.a */
@@ -2116,57 +2138,33 @@ ecma_builtin_array_prototype_fill (ecma_value_t value, /**< value */
ecma_object_t *obj_p, /**< array object */ ecma_object_t *obj_p, /**< array object */
uint32_t len) /**< array object's length */ uint32_t len) /**< array object's length */
{ {
/* 5 */ uint32_t k, final;
ecma_number_t start;
ecma_value_t to_number = ecma_op_to_integer (start_val, &start);
/* 6 */ /* 5. 6. 7. */
if (ECMA_IS_VALUE_ERROR (to_number)) if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (start_val,
len,
&k)))
{ {
return to_number; return ECMA_VALUE_ERROR;
} }
ecma_number_t k; /* 8. */
/* 7 */
if (ecma_number_is_negative (start))
{
k = JERRY_MAX (((ecma_number_t) len + start), 0);
}
else
{
k = JERRY_MIN (start, (ecma_number_t) len);
}
/* 8 */
ecma_number_t relative_end;
if (ecma_is_value_undefined (end_val)) if (ecma_is_value_undefined (end_val))
{ {
relative_end = (ecma_number_t) len; final = len;
} }
else else
{ {
to_number = ecma_op_to_integer (end_val, &relative_end); /* 8 part 2, 9, 10 */
if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (end_val,
if (ECMA_IS_VALUE_ERROR (to_number)) len,
&final)))
{ {
return to_number; return ECMA_VALUE_ERROR;
} }
} }
/* 10 */ /* 11. */
ecma_number_t final;
if (relative_end < 0)
{
final = JERRY_MAX (((ecma_number_t) len + relative_end), 0);
}
else
{
final = JERRY_MIN (relative_end, (ecma_number_t) len);
}
/* 11 */
while (k < final) while (k < final)
{ {
/* 11.a */ /* 11.a */
@@ -2291,49 +2289,39 @@ ecma_builtin_array_prototype_object_copy_within (const ecma_value_t args[], /**<
return ecma_copy_value (ecma_make_object_value (obj_p)); return ecma_copy_value (ecma_make_object_value (obj_p));
} }
ecma_number_t target_num; /* 5 - 7 */
ecma_value_t error = ecma_op_to_integer (args[0], &target_num); uint32_t target;
if (ECMA_IS_VALUE_ERROR (error)) if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (args[0], len, &target)))
{ {
return error; return ECMA_VALUE_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 start = 0;
uint32_t end = len; uint32_t end = len;
if (args_number > 1) if (args_number > 1)
{ {
ecma_number_t start_num; /* 8 - 10 */
error = ecma_op_to_integer (args[1], &start_num); if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (args[1], len, &start)))
if (ECMA_IS_VALUE_ERROR (error))
{ {
return error; return ECMA_VALUE_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 (args_number > 2)
{ {
/* 11 */
if (ecma_is_value_undefined (args[2])) if (ecma_is_value_undefined (args[2]))
{ {
end = len; end = len;
} }
else else
{ {
ecma_number_t end_num; /* 11 part 2, 12, 13 */
error = ecma_op_to_integer (args[2], &end_num); if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (args[2], len, &end)))
if (ECMA_IS_VALUE_ERROR (error))
{ {
return error; return ECMA_VALUE_ERROR;
} }
end = (uint32_t) (ecma_number_is_negative (end_num) ? JERRY_MAX (len + end_num, 0) :
JERRY_MIN (end_num, len));
} }
} }
} }
@@ -2617,8 +2605,8 @@ ecma_builtin_array_prototype_dispatch_routine (uint16_t builtin_routine_id, /**<
} }
case ECMA_ARRAY_PROTOTYPE_INDEX_OF: case ECMA_ARRAY_PROTOTYPE_INDEX_OF:
{ {
ret_value = ecma_builtin_array_prototype_object_index_of (routine_arg_1, ret_value = ecma_builtin_array_prototype_object_index_of (arguments_list_p,
routine_arg_2, arguments_number,
obj_p, obj_p,
length); length);
break; break;
@@ -111,25 +111,23 @@ ecma_builtin_arraybuffer_prototype_object_slice (ecma_value_t this_arg, /**< thi
ecma_value_t ret_value = ECMA_VALUE_EMPTY; ecma_value_t ret_value = ECMA_VALUE_EMPTY;
ECMA_OP_TO_NUMBER_TRY_CATCH (start_num, if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (arg1,
arg1, len,
ret_value); &start)))
{
start = ecma_builtin_helper_array_index_normalize (start_num, len, false); return ECMA_VALUE_ERROR;
}
if (!ecma_is_value_undefined (arg2)) if (!ecma_is_value_undefined (arg2))
{ {
ECMA_OP_TO_NUMBER_TRY_CATCH (end_num, if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (arg2,
arg2, len,
ret_value); &end)))
{
end = ecma_builtin_helper_array_index_normalize (end_num, len, false); return ECMA_VALUE_ERROR;
}
ECMA_OP_TO_NUMBER_FINALIZE (end_num);
} }
ECMA_OP_TO_NUMBER_FINALIZE (start_num);
if (ret_value != ECMA_VALUE_EMPTY) if (ret_value != ECMA_VALUE_EMPTY)
{ {
return ret_value; return ret_value;
@@ -309,93 +309,49 @@ ecma_builtin_helper_object_get_properties (ecma_object_t *obj_p, /**< object */
/** /**
* Helper function to normalizing an array index * 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.
* If is_last_index_of is true, then we use the method in ECMA-262 v6, 22.2.3.16 to compute the normalized index.
* See also: * See also:
* ECMA-262 v5, 15.4.4.10 steps 5-6, 7 (part 2) and 8 * ECMA-262 v5, 15.4.4.10 steps 5, 6, 7 part 2, 8
* ECMA-262 v5, 15.4.4.12 steps 5-6 * 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 - 7
* ECMA-262 v5, 15.5.4.13 steps 4, 5 (part 2) and 6-7 * ECMA-262 v6, 22.1.3.6 steps 5 - 7, 8 part 2, 9, 10
* ECMA-262 v6, 22.1.3.3 steps 5 - 10, 11 part 2, 12, 13
* ECMA-262 v6, 22.2.3.5 steps 5 - 10, 11 part 2, 12, 13
* ECMA-262 v6, 22.2.3.23 steps 5 - 10
* ECMA-262 v6, 24.1.4.3 steps 6 - 8, 9 part 2, 10, 11
* ECMA-262 v6, 22.2.3.26 steps 7 - 9, 10 part 2, 11, 12
* ECMA-262 v6, 22.2.3.8 steps 5 - 7, 8 part 2, 9, 10
* *
* Used by: * Used by:
* - The Array.prototype.slice routine. * - The Array.prototype.slice routine.
* - The Array.prototype.splice routine. * - The Array.prototype.splice routine.
* - The Array.prototype.indexOf routine.
* - The String.prototype.slice routine. * - The String.prototype.slice routine.
* - The TypedArray.prototype.indexOf routine. * - The Array.prototype.fill routine.
* - The TypedArray.prototype.lastIndexOf routine * - The Array.prototype.copyWithin routine.
* - The TypedArray.prototype.copyWithin routine.
* - The TypedArray.prototype.slice routine.
* - The ArrayBuffer.prototype.slice routine.
* - The TypedArray.prototype.subarray routine.
* - The TypedArray.prototype.fill routine.
* *
* @return uint32_t - the normalized value of the index * @return ECMA_VALUE_EMPTY if successful
* conversion error otherwise
*/ */
uint32_t uint32_t
ecma_builtin_helper_array_index_normalize (ecma_number_t index, /**< index */ ecma_builtin_helper_array_index_normalize (ecma_value_t arg, /**< index */
uint32_t length, /**< array's length */ uint32_t length, /**< array's length */
bool is_last_index_of) /**< true - normalize for lastIndexOf method*/ uint32_t *number_p) /**< [out] uint32_t */
{ {
uint32_t norm_index; ecma_number_t to_int;
if (!ecma_number_is_nan (index)) if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (arg, &to_int)))
{ {
return ECMA_VALUE_ERROR;
if (ecma_number_is_zero (index))
{
norm_index = 0;
}
else if (ecma_number_is_infinity (index))
{
if (is_last_index_of)
{
norm_index = ecma_number_is_negative (index) ? (uint32_t) -1 : length - 1;
}
else
{
norm_index = ecma_number_is_negative (index) ? 0 : length;
}
}
else
{
if (ecma_number_is_negative (index))
{
ecma_number_t index_neg = -index;
if (is_last_index_of)
{
norm_index = length - ecma_number_to_uint32 (index_neg);
}
else
{
if (index_neg > length)
{
norm_index = 0;
}
else
{
norm_index = length - ecma_number_to_uint32 (index_neg);
}
}
}
else
{
if (index > length)
{
norm_index = is_last_index_of ? length - 1 : length;
}
else
{
norm_index = ecma_number_to_uint32 (index);
}
}
}
}
else
{
norm_index = 0;
} }
return norm_index; *number_p = ((to_int < 0) ? (uint32_t) JERRY_MAX ((length + to_int), 0)
: (uint32_t) JERRY_MIN (to_int, length));
return ECMA_VALUE_EMPTY;
} /* ecma_builtin_helper_array_index_normalize */ } /* ecma_builtin_helper_array_index_normalize */
/** /**
@@ -596,7 +552,19 @@ ecma_builtin_helper_string_prototype_object_index_of (ecma_string_t *original_st
/* 4 (indexOf, lastIndexOf), 9 (startsWith, includes), 10 (endsWith) */ /* 4 (indexOf, lastIndexOf), 9 (startsWith, includes), 10 (endsWith) */
ecma_number_t pos_num; ecma_number_t pos_num;
ecma_value_t ret_value = ecma_get_number (arg2, &pos_num); ecma_value_t ret_value;
#if ENABLED (JERRY_ES2015)
if (mode > ECMA_STRING_LAST_INDEX_OF)
{
ret_value = ecma_op_to_integer (arg2, &pos_num);
}
else
{
#endif /* ENABLED (JERRY_ES2015) */
ret_value = ecma_get_number (arg2, &pos_num);
#if ENABLED (JERRY_ES2015)
}
#endif /* ENABLED (JERRY_ES2015) */
/* 10 (startsWith, includes), 11 (endsWith) */ /* 10 (startsWith, includes), 11 (endsWith) */
if (ECMA_IS_VALUE_ERROR (ret_value)) if (ECMA_IS_VALUE_ERROR (ret_value))
@@ -34,8 +34,8 @@
typedef enum typedef enum
{ {
/** These routines must be in this order */ /** These routines must be in this order */
ECMA_STRING_INDEX_OF, /**< String.indexOf: ECMA-262 v5, 15.5.4.7 */
ECMA_STRING_LAST_INDEX_OF, /**< String.lastIndexOf: ECMA-262 v5, 15.5.4.8 */ ECMA_STRING_LAST_INDEX_OF, /**< String.lastIndexOf: ECMA-262 v5, 15.5.4.8 */
ECMA_STRING_INDEX_OF, /**< String.indexOf: ECMA-262 v5, 15.5.4.7 */
ECMA_STRING_STARTS_WITH, /**< String.startsWith: ECMA-262 v6, 21.1.3.18 */ ECMA_STRING_STARTS_WITH, /**< String.startsWith: ECMA-262 v6, 21.1.3.18 */
ECMA_STRING_INCLUDES, /**< String.includes: ECMA-262 v6, 21.1.3.7 */ ECMA_STRING_INCLUDES, /**< String.includes: ECMA-262 v6, 21.1.3.7 */
ECMA_STRING_ENDS_WITH /**< String.includes: ECMA-262 v6, 21.1.3.6 */ ECMA_STRING_ENDS_WITH /**< String.includes: ECMA-262 v6, 21.1.3.6 */
@@ -50,7 +50,7 @@ ecma_builtin_helper_object_get_properties (ecma_object_t *obj_p, uint32_t opts);
ecma_value_t ecma_value_t
ecma_builtin_helper_array_concat_value (ecma_object_t *obj_p, uint32_t *length_p, ecma_value_t value); ecma_builtin_helper_array_concat_value (ecma_object_t *obj_p, uint32_t *length_p, ecma_value_t value);
uint32_t uint32_t
ecma_builtin_helper_array_index_normalize (ecma_number_t index, uint32_t length, bool last_index_of); ecma_builtin_helper_array_index_normalize (ecma_value_t arg, uint32_t length, uint32_t *number_p);
uint32_t uint32_t
ecma_builtin_helper_string_index_normalize (ecma_number_t index, uint32_t length, bool nan_to_zero); ecma_builtin_helper_string_index_normalize (ecma_number_t index, uint32_t length, bool nan_to_zero);
ecma_value_t ecma_value_t
@@ -1495,9 +1495,10 @@ ecma_builtin_json_stringify (ecma_value_t this_arg, /**< 'this' argument */
/* 6. */ /* 6. */
if (ecma_is_value_number (space)) if (ecma_is_value_number (space))
{ {
ecma_number_t number = ecma_get_number_from_value (space);
/* 6.a */ /* 6.a */
int32_t num_of_spaces = ecma_number_to_int32 (number); ecma_number_t num_of_spaces;
ecma_op_to_integer (space, &num_of_spaces);
num_of_spaces = JERRY_MIN (10, num_of_spaces); num_of_spaces = JERRY_MIN (10, num_of_spaces);
/* 6.b */ /* 6.b */
@@ -262,7 +262,7 @@ ecma_builtin_number_prototype_object_to_string (ecma_number_t this_arg_number, /
{ {
ecma_number_t arg_num; ecma_number_t arg_num;
if (ECMA_IS_VALUE_ERROR (ecma_get_number (arguments_list_p[0], &arg_num))) if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (arguments_list_p[0], &arg_num)))
{ {
return ECMA_VALUE_ERROR; return ECMA_VALUE_ERROR;
} }
@@ -369,14 +369,14 @@ ecma_builtin_number_prototype_object_to_string (ecma_number_t this_arg_number, /
{ {
for (int i = 0; i < magnitude; i++) for (int i = 0; i < magnitude; i++)
{ {
this_arg_number /= (ecma_number_t) radix; this_arg_number /= radix;
} }
} }
else if (exponent < 0) else if (exponent < 0)
{ {
for (int i = 0; i < magnitude; i++) for (int i = 0; i < magnitude; i++)
{ {
this_arg_number *= (ecma_number_t) radix; this_arg_number *= radix;
} }
} }
@@ -439,7 +439,7 @@ ecma_builtin_number_prototype_object_to_string (ecma_number_t this_arg_number, /
/* Calculate digits for fractional part. */ /* Calculate digits for fractional part. */
while (buff_index < required_digits) while (buff_index < required_digits)
{ {
fraction *= (ecma_number_t) radix; fraction *= radix;
lit_utf8_byte_t digit = (lit_utf8_byte_t) floor (fraction); lit_utf8_byte_t digit = (lit_utf8_byte_t) floor (fraction);
buff[buff_index++] = digit; buff[buff_index++] = digit;
@@ -592,9 +592,9 @@ ecma_builtin_number_prepare_conversion (ecma_number_t *this_num_p, /**< [out] th
JERRY_ASSERT (mode < NUMBER_ROUTINE__COUNT); JERRY_ASSERT (mode < NUMBER_ROUTINE__COUNT);
ecma_number_t arg_num; ecma_number_t arg_num;
arg_1 = ecma_get_number (arg_1, &arg_num); arg_1 = ecma_op_to_integer (arg_1, &arg_num);
if (!ecma_is_value_empty (arg_1)) if (ECMA_IS_VALUE_ERROR (arg_1))
{ {
return arg_1; return arg_1;
} }
@@ -174,7 +174,8 @@ ecma_builtin_number_object_is_integer (ecma_value_t this_arg, /**< this argument
return ECMA_VALUE_FALSE; return ECMA_VALUE_FALSE;
} }
ecma_number_t int_num = ecma_number_trunc (num); ecma_number_t int_num;
ecma_op_to_integer (arg, &int_num);
if (int_num != num) if (int_num != num)
{ {
@@ -80,8 +80,8 @@ enum
ECMA_STRING_PROTOTYPE_REPEAT, ECMA_STRING_PROTOTYPE_REPEAT,
ECMA_STRING_PROTOTYPE_CODE_POINT_AT, ECMA_STRING_PROTOTYPE_CODE_POINT_AT,
/* Note: These 5 routines MUST be in this order */ /* Note: These 5 routines MUST be in this order */
ECMA_STRING_PROTOTYPE_INDEX_OF,
ECMA_STRING_PROTOTYPE_LAST_INDEX_OF, ECMA_STRING_PROTOTYPE_LAST_INDEX_OF,
ECMA_STRING_PROTOTYPE_INDEX_OF,
ECMA_STRING_PROTOTYPE_STARTS_WITH, ECMA_STRING_PROTOTYPE_STARTS_WITH,
ECMA_STRING_PROTOTYPE_INCLUDES, ECMA_STRING_PROTOTYPE_INCLUDES,
ECMA_STRING_PROTOTYPE_ENDS_WITH, ECMA_STRING_PROTOTYPE_ENDS_WITH,
@@ -151,7 +151,7 @@ ecma_builtin_string_prototype_char_at_helper (ecma_value_t this_arg, /**< this a
{ {
/* 3 */ /* 3 */
ecma_number_t index_num; ecma_number_t index_num;
ecma_value_t to_num_result = ecma_get_number (arg, &index_num); ecma_value_t to_num_result = ecma_op_to_integer (arg, &index_num);
if (JERRY_UNLIKELY (!ecma_is_value_empty (to_num_result))) if (JERRY_UNLIKELY (!ecma_is_value_empty (to_num_result)))
{ {
@@ -765,18 +765,16 @@ ecma_builtin_string_prototype_object_slice (ecma_string_t *get_string_val, /**<
{ {
const ecma_length_t len = ecma_string_get_length (get_string_val); const ecma_length_t len = ecma_string_get_length (get_string_val);
/* 4. */ /* 4. 6. */
ecma_length_t start = 0, end = len; ecma_length_t start = 0, end = len;
ecma_number_t start_num; if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (arg1,
len,
if (ECMA_IS_VALUE_ERROR (ecma_get_number (arg1, &start_num))) &start)))
{ {
return ECMA_VALUE_ERROR; return ECMA_VALUE_ERROR;
} }
start = ecma_builtin_helper_array_index_normalize (start_num, len, false);
/* 5. 7. */ /* 5. 7. */
if (ecma_is_value_undefined (arg2)) if (ecma_is_value_undefined (arg2))
{ {
@@ -784,14 +782,12 @@ ecma_builtin_string_prototype_object_slice (ecma_string_t *get_string_val, /**<
} }
else else
{ {
ecma_number_t end_num; if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (arg2,
len,
if (ECMA_IS_VALUE_ERROR (ecma_get_number (arg2, &end_num))) &end)))
{ {
return ECMA_VALUE_ERROR; return ECMA_VALUE_ERROR;
} }
end = ecma_builtin_helper_array_index_normalize (end_num, len, false);
} }
JERRY_ASSERT (start <= len && end <= len); JERRY_ASSERT (start <= len && end <= len);
@@ -1162,35 +1158,37 @@ ecma_builtin_string_prototype_object_substring (ecma_string_t *original_string_p
ecma_value_t arg1, /**< routine's first argument */ ecma_value_t arg1, /**< routine's first argument */
ecma_value_t arg2) /**< routine's second argument */ ecma_value_t arg2) /**< routine's second argument */
{ {
/* 3 */
const ecma_length_t len = ecma_string_get_length (original_string_p); const ecma_length_t len = ecma_string_get_length (original_string_p);
ecma_length_t start = 0, end = len;
/* 4, 6 */ /* 4 */
ecma_number_t start_num; ecma_number_t start_num;
if (ECMA_IS_VALUE_ERROR (ecma_get_number (arg1, &start_num))) if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (arg1, &start_num)))
{ {
return ECMA_VALUE_ERROR; return ECMA_VALUE_ERROR;
} }
ecma_length_t start = 0, end = len; /* 6 */
start = (uint32_t) JERRY_MIN (JERRY_MAX (start_num, 0), len);
start = ecma_builtin_helper_string_index_normalize (start_num, len, true); /* 5 */
/* 5, 7 */
if (ecma_is_value_undefined (arg2)) if (ecma_is_value_undefined (arg2))
{ {
end = len; end = len;
} }
else else
{ {
/* 5 part 2 */
ecma_number_t end_num; ecma_number_t end_num;
if (ECMA_IS_VALUE_ERROR (ecma_get_number (arg2, &end_num))) if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (arg2, &end_num)))
{ {
return ECMA_VALUE_ERROR; return ECMA_VALUE_ERROR;
} }
/* 7 */
end = ecma_builtin_helper_string_index_normalize (end_num, len, true); end = (uint32_t) JERRY_MIN (JERRY_MAX (end_num, 0), len);
} }
JERRY_ASSERT (start <= len && end <= len); JERRY_ASSERT (start <= len && end <= len);
@@ -1354,7 +1352,7 @@ ecma_builtin_string_prototype_object_repeat (ecma_string_t *original_string_p, /
/* 4 */ /* 4 */
ecma_number_t count_number; ecma_number_t count_number;
ecma_value_t count_value = ecma_get_number (repeat, &count_number); ecma_value_t count_value = ecma_op_to_integer (repeat, &count_number);
/* 5 */ /* 5 */
if (ECMA_IS_VALUE_ERROR (count_value)) if (ECMA_IS_VALUE_ERROR (count_value))
@@ -1472,16 +1470,11 @@ ecma_builtin_string_prototype_object_substr (ecma_string_t *this_string_p, /**<
/* 2. */ /* 2. */
ecma_number_t start_num; ecma_number_t start_num;
if (ECMA_IS_VALUE_ERROR (ecma_get_number (start, &start_num))) if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (start, &start_num)))
{ {
return ECMA_VALUE_ERROR; return ECMA_VALUE_ERROR;
} }
if (ecma_number_is_nan (start_num))
{
start_num = 0;
}
/* 3. */ /* 3. */
ecma_number_t length_num = ecma_number_make_infinity (false); ecma_number_t length_num = ecma_number_make_infinity (false);
@@ -1489,7 +1482,7 @@ ecma_builtin_string_prototype_object_substr (ecma_string_t *this_string_p, /**<
{ {
ecma_number_t len; ecma_number_t len;
if (ECMA_IS_VALUE_ERROR (ecma_get_number (length, &len))) if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (length, &len)))
{ {
return ECMA_VALUE_ERROR; return ECMA_VALUE_ERROR;
} }
@@ -1498,15 +1491,21 @@ ecma_builtin_string_prototype_object_substr (ecma_string_t *this_string_p, /**<
} }
/* 4. */ /* 4. */
ecma_number_t this_len = (ecma_number_t) ecma_string_get_length (this_string_p); ecma_length_t this_len = ecma_string_get_length (this_string_p);
/* 5. */ /* 5. */
ecma_number_t from_num = (start_num < 0) ? JERRY_MAX (this_len + start_num, 0) : start_num; uint32_t from = (uint32_t) ((start_num < 0) ? JERRY_MAX (this_len + start_num, 0) : start_num);
uint32_t from = ecma_builtin_helper_string_index_normalize (from_num, ecma_number_to_uint32 (this_len), true);
/* 6-7. */ if (from > this_len)
ecma_number_t to_num = JERRY_MAX (JERRY_MIN (JERRY_MAX (length_num, 0), this_len - from_num), 0); {
uint32_t to = from + ecma_builtin_helper_string_index_normalize (to_num, ecma_number_to_uint32 (this_len), true); from = this_len;
}
/* 6. */
ecma_number_t to_num = JERRY_MIN (JERRY_MAX (length_num, 0), this_len - from);
/* 7. */
uint32_t to = from + (uint32_t) to_num;
/* 8. */ /* 8. */
ecma_string_t *new_str_p = ecma_string_substr (this_string_p, from, to); ecma_string_t *new_str_p = ecma_string_substr (this_string_p, from, to);
@@ -1595,8 +1594,8 @@ ecma_builtin_string_prototype_dispatch_routine (uint16_t builtin_routine_id, /**
ret_value = ecma_builtin_string_prototype_object_slice (string_p, arg1, arg2); ret_value = ecma_builtin_string_prototype_object_slice (string_p, arg1, arg2);
break; break;
} }
case ECMA_STRING_PROTOTYPE_INDEX_OF:
case ECMA_STRING_PROTOTYPE_LAST_INDEX_OF: case ECMA_STRING_PROTOTYPE_LAST_INDEX_OF:
case ECMA_STRING_PROTOTYPE_INDEX_OF:
#if ENABLED (JERRY_ES2015) #if ENABLED (JERRY_ES2015)
case ECMA_STRING_PROTOTYPE_STARTS_WITH: case ECMA_STRING_PROTOTYPE_STARTS_WITH:
case ECMA_STRING_PROTOTYPE_INCLUDES: case ECMA_STRING_PROTOTYPE_INCLUDES:
@@ -1604,7 +1603,7 @@ ecma_builtin_string_prototype_dispatch_routine (uint16_t builtin_routine_id, /**
#endif /* ENABLED (JERRY_ES2015) */ #endif /* ENABLED (JERRY_ES2015) */
{ {
ecma_string_index_of_mode_t mode; ecma_string_index_of_mode_t mode;
mode = (ecma_string_index_of_mode_t) (builtin_routine_id - ECMA_STRING_PROTOTYPE_INDEX_OF); mode = (ecma_string_index_of_mode_t) (builtin_routine_id - ECMA_STRING_PROTOTYPE_LAST_INDEX_OF);
ret_value = ecma_builtin_helper_string_prototype_object_index_of (string_p, arg1, arg2, mode); ret_value = ecma_builtin_helper_string_prototype_object_index_of (string_p, arg1, arg2, mode);
break; break;
} }
@@ -835,16 +835,11 @@ ecma_op_typedarray_set_with_typedarray (ecma_value_t this_arg, /**< this argumen
{ {
/* 6.~ 8. targetOffset */ /* 6.~ 8. targetOffset */
ecma_number_t target_offset_num; ecma_number_t target_offset_num;
if (ECMA_IS_VALUE_ERROR (ecma_get_number (offset_val, &target_offset_num))) if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (offset_val, &target_offset_num)))
{ {
return ECMA_VALUE_ERROR; return ECMA_VALUE_ERROR;
} }
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) 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")); return ecma_raise_range_error (ECMA_ERR_MSG ("Invalid offset"));
@@ -938,12 +933,14 @@ ecma_builtin_typedarray_prototype_set (ecma_value_t this_arg, /**< this argument
} }
/* 6.~ 8. targetOffset */ /* 6.~ 8. targetOffset */
ecma_value_t ret_val = ECMA_VALUE_EMPTY; ecma_number_t target_offset_num;
ECMA_OP_TO_NUMBER_TRY_CATCH (target_offset_num, offset_val, ret_val); ecma_value_t ret_val = ecma_op_to_integer (offset_val, &target_offset_num);
if (ecma_number_is_nan (target_offset_num))
if (ECMA_IS_VALUE_ERROR (ret_val))
{ {
target_offset_num = 0; return ret_val;
} }
if (target_offset_num <= -1.0 || target_offset_num >= (ecma_number_t) UINT32_MAX + 0.5) 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")); return ecma_raise_range_error (ECMA_ERR_MSG ("Invalid offset"));
@@ -1007,7 +1004,6 @@ ecma_builtin_typedarray_prototype_set (ecma_value_t this_arg, /**< this argument
ECMA_FINALIZE (source_length); ECMA_FINALIZE (source_length);
ECMA_FINALIZE (source_obj); ECMA_FINALIZE (source_obj);
ECMA_OP_TO_NUMBER_FINALIZE (target_offset_num);
if (ecma_is_value_empty (ret_val)) if (ecma_is_value_empty (ret_val))
{ {
@@ -1253,9 +1249,12 @@ ecma_builtin_typedarray_prototype_subarray (ecma_value_t this_arg, /**< this arg
uint32_t begin_index_uint32 = 0, end_index_uint32 = 0; uint32_t begin_index_uint32 = 0, end_index_uint32 = 0;
/* 7. relativeBegin */ /* 7. relativeBegin */
ECMA_OP_TO_NUMBER_TRY_CATCH (relative_begin, begin, ret_value); if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (begin,
info.length,
begin_index_uint32 = ecma_builtin_helper_array_index_normalize (relative_begin, info.length, false); &begin_index_uint32)))
{
return ECMA_VALUE_ERROR;
}
if (ecma_is_value_undefined (end)) if (ecma_is_value_undefined (end))
{ {
@@ -1264,15 +1263,14 @@ ecma_builtin_typedarray_prototype_subarray (ecma_value_t this_arg, /**< this arg
else else
{ {
/* 10. relativeEnd */ /* 10. relativeEnd */
ECMA_OP_TO_NUMBER_TRY_CATCH (relative_end, end, ret_value); if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (end,
info.length,
end_index_uint32 = ecma_builtin_helper_array_index_normalize (relative_end, info.length, false); &end_index_uint32)))
{
ECMA_OP_TO_NUMBER_FINALIZE (relative_end); return ECMA_VALUE_ERROR;
}
} }
ECMA_OP_TO_NUMBER_FINALIZE (relative_begin);
if (!ecma_is_value_empty (ret_value)) if (!ecma_is_value_empty (ret_value))
{ {
return ret_value; return ret_value;
@@ -1336,9 +1334,12 @@ ecma_builtin_typedarray_prototype_fill (ecma_value_t this_arg, /**< this argumen
uint32_t begin_index_uint32 = 0, end_index_uint32 = 0; uint32_t begin_index_uint32 = 0, end_index_uint32 = 0;
ECMA_OP_TO_NUMBER_TRY_CATCH (relative_begin, begin, ret_value); if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (begin,
info.length,
begin_index_uint32 = ecma_builtin_helper_array_index_normalize (relative_begin, info.length, false); &begin_index_uint32)))
{
return ECMA_VALUE_ERROR;
}
if (ecma_is_value_undefined (end)) if (ecma_is_value_undefined (end))
{ {
@@ -1346,18 +1347,12 @@ ecma_builtin_typedarray_prototype_fill (ecma_value_t this_arg, /**< this argumen
} }
else else
{ {
ECMA_OP_TO_NUMBER_TRY_CATCH (relative_end, end, ret_value); if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (end,
info.length,
end_index_uint32 = ecma_builtin_helper_array_index_normalize (relative_end, info.length, false); &end_index_uint32)))
{
ECMA_OP_TO_NUMBER_FINALIZE (relative_end); return ECMA_VALUE_ERROR;
} }
ECMA_OP_TO_NUMBER_FINALIZE (relative_begin);
if (!ecma_is_value_empty (ret_value))
{
return ret_value;
} }
ecma_length_t subarray_length = 0; ecma_length_t subarray_length = 0;
@@ -1686,20 +1681,18 @@ ecma_builtin_typedarray_prototype_find_index (ecma_value_t this_arg, /**< this a
} /* ecma_builtin_typedarray_prototype_find_index */ } /* ecma_builtin_typedarray_prototype_find_index */
/** /**
* The %TypedArray%.prototype object's 'indexOf' and 'lastIndexOf' routine helper * The %TypedArray%.prototype object's 'indexOf' routine
* *
* See also: * See also:
* ECMA-262 v6, 22.2.3.13, 22.2.3.16 * ECMA-262 v6, 22.2.3.13
* *
* @return ecma value * @return ecma value
* Returned value must be freed with ecma_free_value. * Returned value must be freed with ecma_free_value.
*/ */
static ecma_value_t static ecma_value_t
ecma_builtin_typedarray_prototype_index_helper (ecma_value_t this_arg, /**< this argument */ ecma_builtin_typedarray_prototype_index_of (ecma_value_t this_arg, /**< this argument */
const ecma_value_t args[], /**< arguments list */ const ecma_value_t args[], /**< arguments list */
ecma_length_t args_number, /**< number of arguments */ ecma_length_t args_number) /**< number of arguments */
bool is_last_index_of) /**< true - lastIndexOf routine
false - indexOf routine */
{ {
if (!ecma_is_typedarray (this_arg)) if (!ecma_is_typedarray (this_arg))
{ {
@@ -1716,6 +1709,7 @@ ecma_builtin_typedarray_prototype_index_helper (ecma_value_t this_arg, /**< this
uint32_t limit = info.length * info.element_size; uint32_t limit = info.length * info.element_size;
uint32_t from_index; uint32_t from_index;
/* 5. */
if (args_number == 0 if (args_number == 0
|| !ecma_is_value_number (args[0]) || !ecma_is_value_number (args[0])
|| info.length == 0) || info.length == 0)
@@ -1724,38 +1718,36 @@ ecma_builtin_typedarray_prototype_index_helper (ecma_value_t this_arg, /**< this
} }
if (args_number == 1) if (args_number == 1)
{ {
from_index = is_last_index_of ? info.length - 1 : 0; from_index = 0;
} }
else else
{ {
/* 6. 7. */
ecma_number_t num_var; ecma_number_t num_var;
if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (args[1], &num_var)))
if (ECMA_IS_VALUE_ERROR (ecma_get_number (args[1], &num_var)))
{ {
return ECMA_VALUE_ERROR; return ECMA_VALUE_ERROR;
} }
/* 8. */
if (!ecma_number_is_nan (num_var) if (num_var >= info.length)
&& is_last_index_of
&& num_var < 0
&& fabs (num_var) > info.length)
{ {
return ecma_make_integer_value (-1); return ecma_make_integer_value (-1);
} }
else
{ /* 9. 10. */
from_index = ecma_builtin_helper_array_index_normalize (num_var, info.length, is_last_index_of); from_index = ((num_var >= 0) ? (uint32_t) num_var
} : (uint32_t) (info.length + num_var));
} }
ecma_number_t search_num = ecma_get_number_from_value (args[0]); ecma_number_t search_num = ecma_get_number_from_value (args[0]);
int32_t increment = is_last_index_of ? -info.element_size : info.element_size;
ecma_typedarray_getter_fn_t getter_cb = ecma_get_typedarray_getter_fn (info.id); ecma_typedarray_getter_fn_t getter_cb = ecma_get_typedarray_getter_fn (info.id);
/* 11. */
for (int32_t position = (int32_t) from_index * info.element_size; for (int32_t position = (int32_t) from_index * info.element_size;
(is_last_index_of ? position >= 0 : (uint32_t) position < limit); (uint32_t) position < limit;
position += increment) position += info.element_size)
{ {
ecma_number_t element_num = getter_cb (info.buffer_p + position); ecma_number_t element_num = getter_cb (info.buffer_p + position);
@@ -1765,24 +1757,8 @@ ecma_builtin_typedarray_prototype_index_helper (ecma_value_t this_arg, /**< this
} }
} }
/* 12. */
return ecma_make_integer_value (-1); return ecma_make_integer_value (-1);
} /* ecma_builtin_typedarray_prototype_index_helper */
/**
* The %TypedArray%.prototype object's 'indexOf' routine
*
* See also:
* ECMA-262 v6, 22.2.3.13
*
* @return ecma value
* Returned value must be freed with ecma_free_value.
*/
static ecma_value_t
ecma_builtin_typedarray_prototype_index_of (ecma_value_t this_arg, /**< this argument */
const ecma_value_t args[], /**< arguments list */
ecma_length_t args_number) /**< number of arguments */
{
return ecma_builtin_typedarray_prototype_index_helper (this_arg, args, args_number, false);
} /* ecma_builtin_typedarray_prototype_index_of */ } /* ecma_builtin_typedarray_prototype_index_of */
/** /**
@@ -1799,40 +1775,72 @@ ecma_builtin_typedarray_prototype_last_index_of (ecma_value_t this_arg, /**< thi
const ecma_value_t args[], /**< arguments list */ const ecma_value_t args[], /**< arguments list */
ecma_length_t args_number) /**< number of arguments */ ecma_length_t args_number) /**< number of arguments */
{ {
return ecma_builtin_typedarray_prototype_index_helper (this_arg, args, args_number, true); if (!ecma_is_typedarray (this_arg))
} /* 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; return ecma_raise_type_error (ECMA_ERR_MSG ("Argument 'this' is not a TypedArray."));
} }
if (is_end_index && ecma_number_is_nan (num_var)) ecma_object_t *typedarray_p = ecma_get_object_from_value (this_arg);
ecma_typedarray_info_t info = ecma_typedarray_get_info (typedarray_p);
if (ecma_arraybuffer_is_detached (info.array_buffer_p))
{ {
*index = length; return ecma_raise_type_error (ECMA_ERR_MSG ("ArrayBuffer has been detached."));
}
uint32_t from_index;
/* 5. */
if (args_number == 0
|| !ecma_is_value_number (args[0])
|| info.length == 0)
{
return ecma_make_integer_value (-1);
}
if (args_number == 1)
{
from_index = info.length - 1;
} }
else else
{ {
*index = ecma_builtin_helper_array_index_normalize (num_var, length, false); /* 6. 7. */
ecma_number_t num_var;
if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (args[1], &num_var)))
{
return ECMA_VALUE_ERROR;
}
if (!ecma_number_is_nan (num_var)
&& -num_var > info.length)
{
return ecma_make_integer_value (-1);
}
/* 8. 9. */
from_index = ((num_var >= 0) ? (uint32_t) JERRY_MIN (num_var, info.length - 1)
: (uint32_t) (info.length + num_var));
} }
return ECMA_VALUE_EMPTY; ecma_number_t search_num = ecma_get_number_from_value (args[0]);
} /* ecma_builtin_get_uint32_value_from_argument */
ecma_typedarray_getter_fn_t getter_cb = ecma_get_typedarray_getter_fn (info.id);
/* 10. */
for (int32_t position = (int32_t) from_index * info.element_size;
position >= 0;
position += -info.element_size)
{
ecma_number_t element_num = getter_cb (info.buffer_p + position);
if (search_num == element_num)
{
return ecma_make_number_value ((ecma_number_t) position / info.element_size);
}
}
/* 11. */
return ecma_make_integer_value (-1);
} /* ecma_builtin_typedarray_prototype_last_index_of */
/** /**
* The %TypedArray%.prototype object's 'copyWithin' routine * The %TypedArray%.prototype object's 'copyWithin' routine
@@ -1855,61 +1863,52 @@ ecma_builtin_typedarray_prototype_copy_within (ecma_value_t this_arg, /**< this
ecma_object_t *typedarray_p = ecma_get_object_from_value (this_arg); ecma_object_t *typedarray_p = ecma_get_object_from_value (this_arg);
ecma_typedarray_info_t info = ecma_typedarray_get_info (typedarray_p); ecma_typedarray_info_t info = ecma_typedarray_get_info (typedarray_p);
uint32_t target = 0; uint32_t relative_target = 0;
uint32_t start = 0; uint32_t relative_start = 0;
uint32_t end = info.length; uint32_t relative_end = info.length;
if (args_number > 0) if (args_number > 0)
{ {
ecma_value_t target_value = ecma_builtin_get_uint32_value_from_argument (args[0], if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (args[0],
info.length, info.length,
&target, &relative_target)))
false);
if (ECMA_IS_VALUE_ERROR (target_value))
{ {
return target_value; return ECMA_VALUE_ERROR;
} }
if (args_number > 1) if (args_number > 1)
{ {
ecma_value_t start_value = ecma_builtin_get_uint32_value_from_argument (args[1], if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (args[1],
info.length, info.length,
&start, &relative_start)))
false);
if (ECMA_IS_VALUE_ERROR (start_value))
{ {
return start_value; return ECMA_VALUE_ERROR;
} }
if (args_number > 2) if (args_number > 2 && args[2] != ECMA_VALUE_UNDEFINED)
{ {
ecma_value_t end_value = ecma_builtin_get_uint32_value_from_argument (args[2], if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (args[2],
info.length, info.length,
&end, &relative_end)))
true);
if (ECMA_IS_VALUE_ERROR (end_value))
{ {
return end_value; return ECMA_VALUE_ERROR;
} }
} }
} }
} }
if (target >= info.length || start >= end || end == 0) if (relative_target >= info.length || relative_start >= relative_end || relative_end == 0)
{ {
return ecma_copy_value (this_arg); return ecma_copy_value (this_arg);
} }
else else
{ {
uint32_t distance = end - start; uint32_t distance = relative_end - relative_start;
uint32_t offset = info.length - target; uint32_t offset = info.length - relative_target;
uint32_t count = JERRY_MIN (distance, offset); uint32_t count = JERRY_MIN (distance, offset);
memmove (info.buffer_p + (target * info.element_size), memmove (info.buffer_p + (relative_target * info.element_size),
info.buffer_p + (start * info.element_size), info.buffer_p + (relative_start * info.element_size),
(size_t) (count * info.element_size)); (size_t) (count * info.element_size));
} }
@@ -1943,36 +1942,29 @@ ecma_builtin_typedarray_prototype_slice (ecma_value_t this_arg, /**< this argume
} }
ecma_typedarray_info_t info = ecma_typedarray_get_info (typedarray_p); ecma_typedarray_info_t info = ecma_typedarray_get_info (typedarray_p);
uint32_t start = 0; uint32_t relative_start = 0;
uint32_t end = info.length; uint32_t relative_end = info.length;
if (args_number > 0) if (args_number > 0)
{ {
ecma_value_t start_value = ecma_builtin_get_uint32_value_from_argument (args[0], if (ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (args[0],
info.length, info.length,
&start, &relative_start)))
false);
if (ECMA_IS_VALUE_ERROR (start_value))
{ {
return start_value; return ECMA_VALUE_ERROR;
} }
if (args_number > 1) if (args_number > 1
&& args[1] != ECMA_VALUE_UNDEFINED
&& ECMA_IS_VALUE_ERROR (ecma_builtin_helper_array_index_normalize (args[1],
info.length,
&relative_end)))
{ {
ecma_value_t end_value = ecma_builtin_get_uint32_value_from_argument (args[1], return ECMA_VALUE_ERROR;
info.length,
&end,
true);
if (ECMA_IS_VALUE_ERROR (end_value))
{
return end_value;
}
} }
} }
int32_t distance = (int32_t) (end - start); int32_t distance = (int32_t) (relative_end - relative_start);
uint32_t count = distance > 0 ? (uint32_t) distance : 0; 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); ecma_value_t new_typedarray = ecma_op_create_typedarray_with_type_and_length (typedarray_p, count);
@@ -1987,7 +1979,7 @@ ecma_builtin_typedarray_prototype_slice (ecma_value_t this_arg, /**< this argume
ecma_object_t *new_typedarray_p = ecma_get_object_from_value (new_typedarray); 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); lit_utf8_byte_t *new_typedarray_buffer_p = ecma_typedarray_get_buffer (new_typedarray_p);
uint32_t src_byte_index = (start * info.element_size); uint32_t src_byte_index = (relative_start * info.element_size);
memcpy (new_typedarray_buffer_p, memcpy (new_typedarray_buffer_p,
info.buffer_p + src_byte_index, info.buffer_p + src_byte_index,
@@ -63,25 +63,27 @@ ecma_op_dataview_create (const ecma_value_t *arguments_list_p, /**< arguments li
} }
/* 4 - 6. */ /* 4 - 6. */
int32_t offset = 0; uint32_t offset = 0;
if (arguments_list_len > 1) if (arguments_list_len > 1)
{ {
ecma_number_t number_offset; ecma_number_t number_offset, offset_num;
ecma_value_t number_offset_value = ecma_get_number (arguments_list_p[1], &number_offset); if (ECMA_IS_VALUE_ERROR (ecma_get_number (arguments_list_p[1], &number_offset)))
if (ECMA_IS_VALUE_ERROR (number_offset_value))
{ {
return number_offset_value; return ECMA_VALUE_ERROR;
}
if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (arguments_list_p[1], &offset_num)))
{
return ECMA_VALUE_ERROR;
} }
offset = ecma_number_to_int32 (number_offset);
/* 7. */ /* 7. */
if (number_offset != offset || offset < 0) if (number_offset != offset_num || offset_num < 0)
{ {
return ecma_raise_range_error (ECMA_ERR_MSG ("Start offset is outside the bounds of the buffer.")); return ecma_raise_range_error (ECMA_ERR_MSG ("Start offset is outside the bounds of the buffer."));
} }
offset = (uint32_t) offset_num;
} }
/* 8. */ /* 8. */
@@ -240,7 +242,7 @@ ecma_op_dataview_get_set_view_value (ecma_value_t view, /**< the operation's 'vi
/* 3 - 5. */ /* 3 - 5. */
ecma_number_t number_index; ecma_number_t number_index;
ecma_value_t number_index_value = ecma_get_number (request_index, &number_index); ecma_value_t number_index_value = ecma_op_to_integer (request_index, &number_index);
if (ECMA_IS_VALUE_ERROR (number_index_value)) if (ECMA_IS_VALUE_ERROR (number_index_value))
{ {
@@ -1308,7 +1308,8 @@ ecma_regexp_exec_helper (ecma_value_t regexp_value, /**< RegExp object */
ecma_value_t lastindex_value = ecma_op_object_get_own_data_prop (regexp_object_p, lastindex_str_p); ecma_value_t lastindex_value = ecma_op_object_get_own_data_prop (regexp_object_p, lastindex_str_p);
ecma_number_t lastindex_num; ecma_number_t lastindex_num;
ret_value = ecma_get_number (lastindex_value, &lastindex_num); ret_value = ecma_op_to_integer (lastindex_value, &lastindex_num);
ecma_free_value (lastindex_value); ecma_free_value (lastindex_value);
if (ECMA_IS_VALUE_ERROR (ret_value)) if (ECMA_IS_VALUE_ERROR (ret_value))
@@ -949,10 +949,13 @@ ecma_op_create_typedarray (const ecma_value_t *arguments_list_p, /**< the arg li
ecma_value_t arg3 = ((arguments_list_len > 2) ? arguments_list_p[2] ecma_value_t arg3 = ((arguments_list_len > 2) ? arguments_list_p[2]
: ECMA_VALUE_UNDEFINED); : ECMA_VALUE_UNDEFINED);
ECMA_OP_TO_NUMBER_TRY_CATCH (num2, arg2, ret); ecma_number_t offset;
uint32_t offset = ecma_number_to_uint32 (num2); if (ECMA_IS_VALUE_ERROR (ecma_op_to_integer (arg2, &offset)))
{
return ECMA_VALUE_ERROR;
}
if (ecma_number_is_negative (ecma_number_to_int32 (num2)) || (offset % (uint32_t) (1 << element_size_shift) != 0)) if (ecma_number_is_negative (offset))
{ {
ret = ecma_raise_range_error (ECMA_ERR_MSG ("Invalid offset.")); ret = ecma_raise_range_error (ECMA_ERR_MSG ("Invalid offset."));
} }
@@ -1007,15 +1010,13 @@ ecma_op_create_typedarray (const ecma_value_t *arguments_list_p, /**< the arg li
{ {
ecma_length_t array_length = new_byte_length >> element_size_shift; ecma_length_t array_length = new_byte_length >> element_size_shift;
ret = ecma_typedarray_create_object_with_buffer (arraybuffer_p, ret = ecma_typedarray_create_object_with_buffer (arraybuffer_p,
offset, (ecma_length_t) offset,
array_length, array_length,
proto_p, proto_p,
element_size_shift, element_size_shift,
typedarray_id); typedarray_id);
} }
} }
ECMA_OP_TO_NUMBER_FINALIZE (num2);
} }
else else
{ {
+4 -5
View File
@@ -168,11 +168,10 @@ gettersSetters.forEach (function (propName) {
var view = new DataView (buffer) var view = new DataView (buffer)
/* ES2015 24.2.1.{1, 2}.6 (numberIndex != getIndex) */ /* ES2015 24.2.1.{1, 2}.6 (numberIndex != getIndex) */
try { if (propName.indexOf("get") !== -1) {
view[propName] (1.5); assert(view[propName] (1.5) === 0);
assert (false); } else {
} catch (e) { assert(view[propName] (1.5) === undefined);
assert (e instanceof RangeError);
} }
/* ES2015 24.2.1.{1, 2}.6 (getIndex < 0) */ /* ES2015 24.2.1.{1, 2}.6 (getIndex < 0) */
@@ -0,0 +1,17 @@
// 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 arrayBufferVar1 = new ArrayBuffer(12, 8);
var arrayVar1 = new Uint8Array(arrayBufferVar1, 9);
arrayVar1.lastIndexOf(15, -Math.LOG10E);
+23
View File
@@ -0,0 +1,23 @@
// 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 text = 'x';
assert (text.charAt(0) === "x");
assert (text.charAt(-0.1) === "x");
assert (text.charAt(-0.5) === "x");
assert (text.charAt(-0.9) === "x");
assert (text.charAt(0.85) === "x");
assert (text.charAt(-0.5) !== "");
assert (text.charAt(0.85) !== "");