Implement {Array, %TypedArray%, String}.prototype.at method (#4681)

The following methods were implemented:
- Array.prototype.at based on ECMA-262 Stage 3 Draft Relative Indexing Method proposal
- String.prototype.at based on ECMA-262 Stage 3 Draft Relative Indexing Method proposal
- TypedArray.prototype.at based on ECMA-262 Stage 3 Draft Relative Indexing Method proposal

https://tc39.es/proposal-relative-indexing-method/

JerryScript-DCO-1.0-Signed-off-by: Daniel Batiz batizjob@gmail.com
This commit is contained in:
batizdaniel
2021-08-10 17:19:25 +02:00
committed by GitHub
parent 444806d78a
commit a25b824509
15 changed files with 363 additions and 1 deletions
@@ -21,6 +21,10 @@
#if JERRY_ESNEXT
SIMPLE_VALUE (LIT_MAGIC_STRING_AT,
ECMA_VALUE_TRUE,
ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE)
SIMPLE_VALUE (LIT_MAGIC_STRING_COPY_WITHIN,
ECMA_VALUE_TRUE,
ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE)
@@ -60,6 +60,7 @@ enum
ECMA_ARRAY_PROTOTYPE_SLICE,
ECMA_ARRAY_PROTOTYPE_SPLICE,
ECMA_ARRAY_PROTOTYPE_UNSHIFT,
ECMA_ARRAY_PROTOTYPE_AT,
ECMA_ARRAY_PROTOTYPE_INDEX_OF,
ECMA_ARRAY_PROTOTYPE_LAST_INDEX_OF,
/* Note these 3 routines must be in this order */
@@ -1609,6 +1610,32 @@ ecma_builtin_array_prototype_object_unshift (const ecma_value_t args[], /**< arg
return ecma_make_number_value (new_len);
} /* ecma_builtin_array_prototype_object_unshift */
/**
* The Array.prototype object's 'at' routine
*
* See also:
* ECMA-262 Stage 3 Draft Relative Indexing Method proposal
* from: https://tc39.es/proposal-relative-indexing-method
*
* @return ecma value
* Returned value must be freed with ecma_free_value.
*/
static ecma_value_t
ecma_builtin_array_prototype_object_at (const ecma_value_t index, /**< index argument */
ecma_object_t *obj_p, /**< object */
ecma_length_t len) /**< object's length */
{
ecma_length_t res_index;
ecma_value_t return_value = ecma_builtin_helper_calculate_index (index, len, &res_index);
if (return_value != ECMA_VALUE_EMPTY)
{
return return_value;
}
return ecma_op_object_get_by_index (obj_p, res_index);
} /* ecma_builtin_array_prototype_object_at */
/**
* The Array.prototype object's 'indexOf' routine
*
@@ -3012,6 +3039,13 @@ ecma_builtin_array_prototype_dispatch_routine (uint8_t builtin_routine_id, /**<
length);
break;
}
case ECMA_ARRAY_PROTOTYPE_AT:
{
ret_value = ecma_builtin_array_prototype_object_at (routine_arg_1,
obj_p,
length);
break;
}
case ECMA_ARRAY_PROTOTYPE_INDEX_OF:
{
ret_value = ecma_builtin_array_prototype_object_index_of (arguments_list_p,
@@ -58,6 +58,7 @@ ROUTINE (LIT_MAGIC_STRING_REVERSE, ECMA_ARRAY_PROTOTYPE_REVERSE, 0, 0)
ROUTINE (LIT_MAGIC_STRING_SHIFT, ECMA_ARRAY_PROTOTYPE_SHIFT, 0, 0)
ROUTINE (LIT_MAGIC_STRING_SLICE, ECMA_ARRAY_PROTOTYPE_SLICE, 2, 2)
ROUTINE (LIT_MAGIC_STRING_SORT, ECMA_ARRAY_PROTOTYPE_SORT, 1, 1)
ROUTINE (LIT_MAGIC_STRING_AT, ECMA_ARRAY_PROTOTYPE_AT, 1, 1)
ROUTINE (LIT_MAGIC_STRING_SPLICE, ECMA_ARRAY_PROTOTYPE_SPLICE, NON_FIXED, 2)
ROUTINE (LIT_MAGIC_STRING_UNSHIFT, ECMA_ARRAY_PROTOTYPE_UNSHIFT, NON_FIXED, 1)
ROUTINE (LIT_MAGIC_STRING_INDEX_OF_UL, ECMA_ARRAY_PROTOTYPE_INDEX_OF, 2, 1)
@@ -817,6 +817,60 @@ ecma_builtin_helper_def_prop_by_index (ecma_object_t *obj_p, /**< object */
return ret_value;
} /* ecma_builtin_helper_def_prop_by_index */
/**
* Helper function for at() functions.
*
* See also:
* ECMA-262 Stage 3 Draft Relative Indexing Method proposal 3. 4. 5. 6.
*
* Used by:
* - The Array.prototype.at routine.
* - The String.prototype.at routine.
* - The TypedArray.prototype.at routine.
*
* @return ECMA_VALUE_ERROR - on conversion error
* ECMA_VALUE_UNDEFINED - if the requested index is not exist
* ECMA_VALUE_EMPTY - otherwise
*/
ecma_value_t
ecma_builtin_helper_calculate_index (ecma_value_t index, /**< relative index argument */
ecma_length_t length, /**< object's length */
ecma_length_t *out_index) /**< calculated index */
{
JERRY_ASSERT (out_index != NULL);
ecma_number_t relative_index;
ecma_value_t conversion_result = ecma_op_to_integer (index, &relative_index);
/* 4. */
if (ECMA_IS_VALUE_ERROR (conversion_result))
{
return ECMA_VALUE_ERROR;
}
/* 5. 6. */
ecma_number_t k;
if (relative_index >= 0)
{
k = relative_index;
}
else
{
k = ((ecma_number_t) length + relative_index);
}
/* 7. */
if (k < 0 || k >= ((ecma_number_t) length))
{
return ECMA_VALUE_UNDEFINED;
}
*out_index = (ecma_length_t) k;
return ECMA_VALUE_EMPTY;
} /* ecma_builtin_helper_calculate_index */
/**
* Helper function for using [[DefineOwnProperty]].
*
@@ -65,6 +65,9 @@ ecma_builtin_helper_def_prop (ecma_object_t *obj_p, ecma_string_t *name_p, ecma_
ecma_value_t
ecma_builtin_helper_def_prop_by_index (ecma_object_t *obj_p, ecma_length_t index, ecma_value_t value,
uint32_t opts);
ecma_value_t
ecma_builtin_helper_calculate_index (ecma_value_t index, ecma_length_t length, ecma_length_t *out_index);
/**
* Context for replace substitutions
*/
@@ -61,6 +61,7 @@ enum
ECMA_STRING_PROTOTYPE_CONCAT,
ECMA_STRING_PROTOTYPE_SLICE,
ECMA_STRING_PROTOTYPE_AT,
ECMA_STRING_PROTOTYPE_LOCALE_COMPARE,
@@ -920,6 +921,34 @@ ecma_builtin_string_prototype_object_slice (ecma_string_t *get_string_val, /**<
return ecma_make_string_value (new_str_p);
} /* ecma_builtin_string_prototype_object_slice */
/**
* The String.prototype object's 'at' routine
*
* See also:
* ECMA-262 Stage 3 Draft Relative Indexing Method proposal
* from: https://tc39.es/proposal-relative-indexing-method
*
* @return ecma value
* Returned value must be freed with ecma_free_value.
*/
static ecma_value_t
ecma_builtin_string_prototype_object_at (ecma_string_t *string_val, /**< this argument */
const ecma_value_t index) /**< index argument */
{
ecma_length_t len = (ecma_length_t) ecma_string_get_length (string_val);
ecma_length_t res_index;
ecma_value_t return_value = ecma_builtin_helper_calculate_index (index, len, &res_index);
if (return_value != ECMA_VALUE_EMPTY)
{
return return_value;
}
ecma_char_t character = ecma_string_get_char_at_pos (string_val, (lit_utf8_size_t) res_index);
return ecma_make_string_value (ecma_new_ecma_string_from_code_unit (character));
} /* ecma_builtin_string_prototype_object_at */
/**
* The String.prototype object's 'split' routine
*
@@ -1536,6 +1565,11 @@ ecma_builtin_string_prototype_dispatch_routine (uint8_t builtin_routine_id, /**<
ret_value = ecma_builtin_string_prototype_object_slice (string_p, arg1, arg2);
break;
}
case ECMA_STRING_PROTOTYPE_AT:
{
ret_value = ecma_builtin_string_prototype_object_at (string_p, arg1);
break;
}
case ECMA_STRING_PROTOTYPE_LAST_INDEX_OF:
case ECMA_STRING_PROTOTYPE_INDEX_OF:
#if JERRY_ESNEXT
@@ -43,6 +43,7 @@ ROUTINE (LIT_MAGIC_STRING_TO_STRING_UL, ECMA_STRING_PROTOTYPE_TO_STRING, 0, 0)
ROUTINE (LIT_MAGIC_STRING_VALUE_OF_UL, ECMA_STRING_PROTOTYPE_VALUE_OF, 0, 0)
ROUTINE (LIT_MAGIC_STRING_CONCAT, ECMA_STRING_PROTOTYPE_CONCAT, NON_FIXED, 1)
ROUTINE (LIT_MAGIC_STRING_SLICE, ECMA_STRING_PROTOTYPE_SLICE, 2, 2)
ROUTINE (LIT_MAGIC_STRING_AT, ECMA_STRING_PROTOTYPE_AT, 1, 1)
ROUTINE (LIT_MAGIC_STRING_INDEX_OF_UL, ECMA_STRING_PROTOTYPE_INDEX_OF, 2, 1)
ROUTINE (LIT_MAGIC_STRING_LAST_INDEX_OF_UL, ECMA_STRING_PROTOTYPE_LAST_INDEX_OF, 2, 1)
ROUTINE (LIT_MAGIC_STRING_CHAR_AT_UL, ECMA_STRING_PROTOTYPE_CHAR_AT, 1, 1)
@@ -65,6 +65,7 @@ enum
ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_FIND_INDEX,
ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_INDEX_OF,
ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_AT,
ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_LAST_INDEX_OF,
ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_INCLUDES,
ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_FILL,
@@ -1297,6 +1298,32 @@ ecma_builtin_typedarray_prototype_find_helper (ecma_value_t this_arg, /**< this
return is_find ? ECMA_VALUE_UNDEFINED : ecma_make_integer_value (-1);
} /* ecma_builtin_typedarray_prototype_find_helper */
/**
* The %TypedArray%.prototype object's 'at' routine
*
* See also:
* ECMA-262 Stage 3 Draft Relative Indexing Method proposal
* from: https://tc39.es/proposal-relative-indexing-method
*
* @return ecma value
* Returned value must be freed with ecma_free_value.
*/
static ecma_value_t
ecma_builtin_typedarray_prototype_at (ecma_typedarray_info_t *info_p, /**< object info */
const ecma_value_t index) /**< index argument */
{
ecma_length_t len = (ecma_length_t) info_p->length;
ecma_length_t res_index;
ecma_value_t return_value = ecma_builtin_helper_calculate_index (index, len, &res_index);
if (return_value != ECMA_VALUE_EMPTY)
{
return return_value;
}
return ecma_get_typedarray_element (info_p, (ecma_number_t) res_index);
} /* ecma_builtin_typedarray_prototype_at */
/**
* The %TypedArray%.prototype object's 'indexOf' routine
*
@@ -1855,6 +1882,10 @@ ecma_builtin_typedarray_prototype_dispatch_routine (uint8_t builtin_routine_id,
arguments_list_p[1],
is_find);
}
case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_AT:
{
return ecma_builtin_typedarray_prototype_at (&info, arguments_list_p[0]);
}
case ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_INDEX_OF:
{
return ecma_builtin_typedarray_prototype_index_of (&info, arguments_list_p, arguments_number);
@@ -61,6 +61,7 @@ ROUTINE (LIT_MAGIC_STRING_FIND, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_FIND, 2, 1)
ROUTINE (LIT_MAGIC_STRING_FIND_INDEX, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_FIND_INDEX, 2, 1)
ROUTINE (LIT_MAGIC_STRING_FOR_EACH_UL, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_FOR_EACH, 2, 1)
ROUTINE (LIT_MAGIC_STRING_INCLUDES, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_INCLUDES, NON_FIXED, 1)
ROUTINE (LIT_MAGIC_STRING_AT, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_AT, 1, 1)
ROUTINE (LIT_MAGIC_STRING_INDEX_OF_UL, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_INDEX_OF, NON_FIXED, 1)
ROUTINE (LIT_MAGIC_STRING_JOIN, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_JOIN, 1, 1)
ROUTINE (LIT_MAGIC_STRING_KEYS, ECMA_TYPEDARRAY_PROTOTYPE_ROUTINE_KEYS, 0, 0)