Skip to content

Commit eca1ec4

Browse files
committed
Array.prototype.sort() now handles defined properties only.
JerryScript-DCO-1.0-Signed-off-by: Dániel Bátyai dbatyai.u-szeged@partner.samsung.com
1 parent 9f6bded commit eca1ec4

File tree

4 files changed

+112
-38
lines changed

4 files changed

+112
-38
lines changed

jerry-core/ecma/base/ecma-helpers-string.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -992,6 +992,39 @@ ecma_string_to_number (const ecma_string_t *str_p) /**< ecma-string */
992992
JERRY_UNREACHABLE ();
993993
} /* ecma_string_to_number */
994994

995+
/**
996+
* Check if string is array index.
997+
*
998+
* @return true - if string is valid array index
999+
* false - otherwise
1000+
*/
1001+
bool
1002+
ecma_string_get_array_index (const ecma_string_t *str_p, /**< ecma-string */
1003+
uint32_t *out_index_p) /**< out: index */
1004+
{
1005+
bool is_array_index = true;
1006+
if (str_p->container == ECMA_STRING_CONTAINER_UINT32_IN_DESC)
1007+
{
1008+
*out_index_p = str_p->u.uint32_number;
1009+
}
1010+
else
1011+
{
1012+
ecma_number_t num = ecma_string_to_number (str_p);
1013+
*out_index_p = ecma_number_to_uint32 (num);
1014+
1015+
ecma_string_t *to_uint32_to_string_p = ecma_new_ecma_string_from_uint32 (*out_index_p);
1016+
1017+
is_array_index = ecma_compare_ecma_strings (str_p,
1018+
to_uint32_to_string_p);
1019+
1020+
ecma_deref_ecma_string (to_uint32_to_string_p);
1021+
}
1022+
1023+
is_array_index = is_array_index && (*out_index_p != ECMA_MAX_VALUE_OF_VALID_ARRAY_INDEX);
1024+
1025+
return is_array_index;
1026+
} /* ecma_string_is_array_index */
1027+
9951028
/**
9961029
* Convert ecma-string's contents to a utf-8 string and put it to the buffer.
9971030
*

jerry-core/ecma/base/ecma-helpers.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ extern ecma_string_t* ecma_copy_or_ref_ecma_string (ecma_string_t *string_desc_p
125125
extern void ecma_deref_ecma_string (ecma_string_t *string_p);
126126
extern void ecma_check_that_ecma_string_need_not_be_freed (const ecma_string_t *string_p);
127127
extern ecma_number_t ecma_string_to_number (const ecma_string_t *str_p);
128+
extern bool ecma_string_get_array_index (const ecma_string_t *str_p, uint32_t *index);
128129
extern ssize_t ecma_string_to_utf8_string (const ecma_string_t *string_desc_p,
129130
lit_utf8_byte_t *buffer_p,
130131
ssize_t buffer_size);

jerry-core/ecma/builtin-objects/ecma-builtin-array-prototype.cpp

Lines changed: 77 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1449,36 +1449,75 @@ ecma_builtin_array_prototype_object_sort (ecma_value_t this_arg, /**< this argum
14491449
uint32_t len = ecma_number_to_uint32 (len_number);
14501450

14511451
uint32_t defined_prop_count = 0;
1452-
/* Count number of defined properties. */
1452+
/* Count number of array index properties. */
14531453
for (ecma_property_t *property_p = ecma_get_property_list (obj_p);
14541454
property_p != NULL;
14551455
property_p = ECMA_GET_POINTER (ecma_property_t, property_p->next_property_p))
14561456
{
1457-
defined_prop_count++;
1457+
ecma_string_t *property_name_p;
1458+
1459+
if (property_p->type == ECMA_PROPERTY_NAMEDDATA)
1460+
{
1461+
property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
1462+
property_p->u.named_data_property.name_p);
1463+
}
1464+
else if (property_p->type == ECMA_PROPERTY_NAMEDACCESSOR)
1465+
{
1466+
property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
1467+
property_p->u.named_accessor_property.name_p);
1468+
}
1469+
else
1470+
{
1471+
continue;
1472+
}
1473+
1474+
uint32_t index;
1475+
if (ecma_string_get_array_index (property_name_p, &index) && index < len)
1476+
{
1477+
defined_prop_count++;
1478+
}
14581479
}
14591480

14601481
MEM_DEFINE_LOCAL_ARRAY (values_buffer, defined_prop_count, ecma_value_t);
14611482
uint32_t copied_num = 0;
14621483

14631484
/* Copy unsorted array into a native c array. */
1464-
for (uint32_t index = 0; index < len && ecma_is_completion_value_empty (ret_value); index++)
1485+
for (ecma_property_t *property_p = ecma_get_property_list (obj_p);
1486+
property_p != NULL && ecma_is_completion_value_empty (ret_value);
1487+
property_p = ECMA_GET_POINTER (ecma_property_t, property_p->next_property_p))
14651488
{
1466-
ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index);
1467-
if (ecma_op_object_get_property (obj_p, index_string_p) != NULL)
1489+
ecma_string_t *property_name_p;
1490+
1491+
if (property_p->type == ECMA_PROPERTY_NAMEDDATA)
1492+
{
1493+
property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
1494+
property_p->u.named_data_property.name_p);
1495+
}
1496+
else if (property_p->type == ECMA_PROPERTY_NAMEDACCESSOR)
1497+
{
1498+
property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
1499+
property_p->u.named_accessor_property.name_p);
1500+
}
1501+
else
14681502
{
1469-
ECMA_TRY_CATCH (index_value, ecma_op_object_get (obj_p, index_string_p), ret_value);
1503+
continue;
1504+
}
1505+
1506+
uint32_t index;
1507+
if (ecma_string_get_array_index (property_name_p, &index) && index < len)
1508+
{
1509+
ECMA_TRY_CATCH (index_value, ecma_op_object_get (obj_p, property_name_p), ret_value);
14701510

14711511
values_buffer[copied_num++] = ecma_copy_value (index_value, true);
14721512

14731513
ECMA_FINALIZE (index_value);
14741514
}
1475-
ecma_deref_ecma_string (index_string_p);
14761515
}
14771516

1478-
JERRY_ASSERT (copied_num <= defined_prop_count);
1517+
JERRY_ASSERT (copied_num == defined_prop_count || !ecma_is_completion_value_empty (ret_value));
14791518

14801519
/* Sorting. */
1481-
if (len > 1 && ecma_is_completion_value_empty (ret_value))
1520+
if (copied_num > 1 && ecma_is_completion_value_empty (ret_value))
14821521
{
14831522
ECMA_TRY_CATCH (sort_value,
14841523
ecma_builtin_array_prototype_object_array_heap_sort_helper (values_buffer,
@@ -1489,8 +1528,7 @@ ecma_builtin_array_prototype_object_sort (ecma_value_t this_arg, /**< this argum
14891528
}
14901529

14911530
/* Put sorted values to the front of the array. */
1492-
uint32_t index;
1493-
for (index = 0; index < copied_num && ecma_is_completion_value_empty (ret_value); index++)
1531+
for (uint32_t index = 0; index < copied_num && ecma_is_completion_value_empty (ret_value); index++)
14941532
{
14951533
ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index);
14961534
ECMA_TRY_CATCH (put_value,
@@ -1501,12 +1539,35 @@ ecma_builtin_array_prototype_object_sort (ecma_value_t this_arg, /**< this argum
15011539
}
15021540

15031541
/* Undefined properties should be in the back of the array. */
1504-
for (;index < len && ecma_is_completion_value_empty (ret_value); index++)
1542+
ecma_property_t *next_prop;
1543+
for (ecma_property_t *property_p = ecma_get_property_list (obj_p);
1544+
property_p != NULL && ecma_is_completion_value_empty (ret_value);
1545+
property_p = next_prop)
15051546
{
1506-
ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index);
1507-
ECMA_TRY_CATCH (del_value, ecma_op_object_delete (obj_p, index_string_p, true), ret_value);
1508-
ECMA_FINALIZE (del_value);
1509-
ecma_deref_ecma_string (index_string_p);
1547+
ecma_string_t *property_name_p;
1548+
next_prop = ECMA_GET_POINTER (ecma_property_t, property_p->next_property_p);
1549+
1550+
if (property_p->type == ECMA_PROPERTY_NAMEDDATA)
1551+
{
1552+
property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
1553+
property_p->u.named_data_property.name_p);
1554+
}
1555+
else if (property_p->type == ECMA_PROPERTY_NAMEDACCESSOR)
1556+
{
1557+
property_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t,
1558+
property_p->u.named_accessor_property.name_p);
1559+
}
1560+
else
1561+
{
1562+
continue;
1563+
}
1564+
1565+
uint32_t index;
1566+
if (ecma_string_get_array_index (property_name_p, &index) && index < len && index >= copied_num)
1567+
{
1568+
ECMA_TRY_CATCH (del_value, ecma_op_object_delete (obj_p, property_name_p, true), ret_value);
1569+
ECMA_FINALIZE (del_value);
1570+
}
15101571
}
15111572

15121573
/* Free values that were copied to the local array. */

jerry-core/ecma/operations/ecma-array-object.cpp

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -386,29 +386,8 @@ ecma_op_array_object_define_own_property (ecma_object_t *obj_p, /**< the array o
386386
{
387387
// 4.a.
388388
uint32_t index;
389-
bool is_index;
390389

391-
if (property_name_p->container == ECMA_STRING_CONTAINER_UINT32_IN_DESC)
392-
{
393-
index = property_name_p->u.uint32_number;
394-
is_index = true;
395-
}
396-
else
397-
{
398-
ecma_number_t number = ecma_string_to_number (property_name_p);
399-
index = ecma_number_to_uint32 (number);
400-
401-
ecma_string_t *to_uint32_to_string_p = ecma_new_ecma_string_from_uint32 (index);
402-
403-
is_index = ecma_compare_ecma_strings (property_name_p,
404-
to_uint32_to_string_p);
405-
406-
ecma_deref_ecma_string (to_uint32_to_string_p);
407-
}
408-
409-
is_index = is_index && (index != ECMA_MAX_VALUE_OF_VALID_ARRAY_INDEX);
410-
411-
if (!is_index)
390+
if (!ecma_string_get_array_index (property_name_p, &index))
412391
{
413392
// 5.
414393
return ecma_op_general_object_define_own_property (obj_p,

0 commit comments

Comments
 (0)