@@ -1435,6 +1435,311 @@ ecma_builtin_array_prototype_object_slice (ecma_value_t this_arg, /**< 'this' ar
14351435 return ret_value;
14361436} /* ecma_builtin_array_prototype_object_slice */
14371437
1438+ /* *
1439+ * The Array.prototype object's 'splice' routine
1440+ *
1441+ * See also:
1442+ * ECMA-262 v5, 15.4.4.12
1443+ *
1444+ * @return completion value
1445+ * Returned value must be freed with ecma_free_completion_value.
1446+ */
1447+ static ecma_completion_value_t
1448+ ecma_builtin_array_prototype_object_splice (ecma_value_t this_arg, /* *< this argument */
1449+ const ecma_value_t args[], /* *< arguments list */
1450+ ecma_length_t args_number) /* *< number of arguments */
1451+ {
1452+ ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
1453+
1454+ /* 1. */
1455+ ECMA_TRY_CATCH (obj_this,
1456+ ecma_op_to_object (this_arg),
1457+ ret_value);
1458+
1459+ ecma_object_t *obj_p = ecma_get_object_from_value (obj_this);
1460+
1461+ /* 3. */
1462+ ecma_string_t *length_magic_string_p = ecma_get_magic_string (ECMA_MAGIC_STRING_LENGTH);
1463+
1464+ ECMA_TRY_CATCH (len_value,
1465+ ecma_op_object_get (obj_p, length_magic_string_p),
1466+ ret_value);
1467+
1468+ /* 4. */
1469+ ECMA_OP_TO_NUMBER_TRY_CATCH (len_number,
1470+ len_value,
1471+ ret_value);
1472+
1473+ const uint32_t len = ecma_number_to_uint32 (len_number);
1474+
1475+ ecma_completion_value_t new_array = ecma_op_create_array_object (0 , 0 , false );
1476+ ecma_object_t *new_array_p = ecma_get_object_from_completion_value (new_array);
1477+
1478+ uint32_t start = 0 ;
1479+ uint32_t delete_count = 0 ;
1480+
1481+ if (args_number > 0 )
1482+ {
1483+ /* 5. */
1484+ ECMA_OP_TO_NUMBER_TRY_CATCH (start_num,
1485+ args[0 ],
1486+ ret_value);
1487+
1488+ int32_t relative_start = ecma_number_to_int32 (start_num);
1489+
1490+ /* 6. */
1491+ if (relative_start < 0 )
1492+ {
1493+ uint32_t start_abs = (uint32_t ) - relative_start;
1494+ if (start_abs > len)
1495+ {
1496+ start = 0 ;
1497+ }
1498+ else
1499+ {
1500+ start = len - start_abs;
1501+ }
1502+ }
1503+ else
1504+ {
1505+ start = (uint32_t ) relative_start;
1506+ if (start > len)
1507+ {
1508+ start = len;
1509+ }
1510+ }
1511+
1512+ /*
1513+ * If there is only one argument, that will be the start argument,
1514+ * and we must delete the additional elements.
1515+ */
1516+ if (args_number == 1 )
1517+ {
1518+ delete_count = len - start;
1519+ }
1520+ else
1521+ {
1522+ /* 7. */
1523+ ECMA_OP_TO_NUMBER_TRY_CATCH (delete_num,
1524+ args[1 ],
1525+ ret_value);
1526+
1527+ int32_t delete_count_int = ecma_number_to_int32 (delete_num);
1528+
1529+ if (delete_count_int > 0 )
1530+ {
1531+ delete_count = (uint32_t ) delete_count_int;
1532+ }
1533+ else
1534+ {
1535+ delete_count = 0 ;
1536+ }
1537+
1538+ if (len - start < delete_count)
1539+ {
1540+ delete_count = len - start;
1541+ }
1542+
1543+ ECMA_OP_TO_NUMBER_FINALIZE (delete_num);
1544+ }
1545+
1546+ ECMA_OP_TO_NUMBER_FINALIZE (start_num);
1547+ }
1548+
1549+ /* 8-9. */
1550+ uint32_t k;
1551+
1552+ for (uint32_t del_item_idx, k = 0 ;
1553+ k < delete_count && ecma_is_completion_value_empty (ret_value);
1554+ k++)
1555+ {
1556+ /* 9.a */
1557+ del_item_idx = k + start;
1558+ ecma_string_t *idx_str_p = ecma_new_ecma_string_from_uint32 (del_item_idx);
1559+
1560+ /* 9.b */
1561+ if (ecma_op_object_get_property (obj_p, idx_str_p) != NULL )
1562+ {
1563+ /* 9.c.i */
1564+ ECMA_TRY_CATCH (get_value,
1565+ ecma_op_object_get (obj_p, idx_str_p),
1566+ ret_value);
1567+
1568+ ecma_string_t *idx_str_new_p = ecma_new_ecma_string_from_uint32 (k);
1569+
1570+ /* 9.c.ii
1571+ * Using [[Put]] is equivalent to using [[DefineOwnProperty]] as specified the standard,
1572+ * so we use [[Put]] instead for simplicity. No need for a try-catch block since it is called
1573+ * with is_throw = false.
1574+ */
1575+ ECMA_TRY_CATCH (put_value,
1576+ ecma_op_object_put (new_array_p, idx_str_new_p, get_value, false ),
1577+ ret_value);
1578+
1579+ ECMA_FINALIZE (put_value);
1580+ ecma_deref_ecma_string (idx_str_new_p);
1581+ ECMA_FINALIZE (get_value);
1582+ }
1583+
1584+ ecma_deref_ecma_string (idx_str_p);
1585+ }
1586+
1587+ /* 11. */
1588+ ecma_length_t item_count;
1589+
1590+ if (args_number > 2 )
1591+ {
1592+ item_count = (ecma_length_t ) (args_number - 2 );
1593+ }
1594+ else
1595+ {
1596+ item_count = 0 ;
1597+ }
1598+
1599+ const uint32_t new_len = len - delete_count + item_count;
1600+
1601+ if (item_count != delete_count)
1602+ {
1603+ uint32_t from, to;
1604+
1605+ /* 12. */
1606+ if (item_count < delete_count)
1607+ {
1608+ /* 12.b */
1609+ for (k = start; k < (len - delete_count) && ecma_is_completion_value_empty (ret_value); k++)
1610+ {
1611+ from = k + delete_count;
1612+ ecma_string_t *from_str_p = ecma_new_ecma_string_from_uint32 (from);
1613+
1614+ to = k + item_count;
1615+ ecma_string_t *to_str_p = ecma_new_ecma_string_from_uint32 (to);
1616+
1617+ /* 12.b.iii */
1618+ if (ecma_op_object_get_property (obj_p, from_str_p) != NULL )
1619+ {
1620+ /* 12.b.iv */
1621+ ECMA_TRY_CATCH (get_value,
1622+ ecma_op_object_get (obj_p, from_str_p),
1623+ ret_value);
1624+
1625+ ECMA_TRY_CATCH (put_value,
1626+ ecma_op_object_put (obj_p, to_str_p, get_value, true ),
1627+ ret_value);
1628+
1629+ ECMA_FINALIZE (put_value);
1630+ ECMA_FINALIZE (get_value);
1631+ }
1632+ else
1633+ {
1634+ /* 12.b.v */
1635+ ECMA_TRY_CATCH (del_value,
1636+ ecma_op_object_delete (obj_p, to_str_p, true ),
1637+ ret_value);
1638+
1639+ ECMA_FINALIZE (del_value);
1640+ }
1641+
1642+ ecma_deref_ecma_string (to_str_p);
1643+ ecma_deref_ecma_string (from_str_p);
1644+ }
1645+
1646+ /* 12.d */
1647+ for (k = len; k > new_len && ecma_is_completion_value_empty (ret_value); k--)
1648+ {
1649+ ecma_string_t *str_idx_p = ecma_new_ecma_string_from_uint32 (k - 1 );
1650+ ECMA_TRY_CATCH (del_value,
1651+ ecma_op_object_delete (obj_p, str_idx_p, true ),
1652+ ret_value);
1653+
1654+ ECMA_FINALIZE (del_value);
1655+ ecma_deref_ecma_string (str_idx_p);
1656+ }
1657+ }
1658+ /* 13. */
1659+ else if (item_count > delete_count)
1660+ {
1661+ /* 13.b */
1662+ for (k = len - delete_count; k > start && ecma_is_completion_value_empty (ret_value); k--)
1663+ {
1664+ from = k + delete_count - 1 ;
1665+ ecma_string_t *from_str_p = ecma_new_ecma_string_from_uint32 (from);
1666+
1667+ to = k + item_count - 1 ;
1668+ ecma_string_t *to_str_p = ecma_new_ecma_string_from_uint32 (to);
1669+
1670+ /* 13.b.iii */
1671+ if (ecma_op_object_get_property (obj_p, from_str_p) != NULL )
1672+ {
1673+ /* 13.b.iv */
1674+ ECMA_TRY_CATCH (get_value,
1675+ ecma_op_object_get (obj_p, from_str_p),
1676+ ret_value);
1677+
1678+ ECMA_TRY_CATCH (put_value,
1679+ ecma_op_object_put (obj_p, to_str_p, get_value, true ),
1680+ ret_value);
1681+
1682+ ECMA_FINALIZE (put_value);
1683+ ECMA_FINALIZE (get_value);
1684+ }
1685+ else
1686+ {
1687+ /* 13.b.v */
1688+ ECMA_TRY_CATCH (del_value,
1689+ ecma_op_object_delete (obj_p, to_str_p, true ),
1690+ ret_value);
1691+
1692+ ECMA_FINALIZE (del_value);
1693+ }
1694+
1695+ ecma_deref_ecma_string (to_str_p);
1696+ ecma_deref_ecma_string (from_str_p);
1697+ }
1698+ }
1699+ }
1700+
1701+ /* 15. */
1702+ ecma_length_t idx = 0 ;
1703+ for (ecma_length_t arg_index = 2 ;
1704+ arg_index < args_number && ecma_is_completion_value_empty (ret_value);
1705+ arg_index++, idx++)
1706+ {
1707+ ecma_string_t *str_idx_p = ecma_new_ecma_string_from_uint32 ((uint32_t ) (start + idx));
1708+ ECMA_TRY_CATCH (put_value,
1709+ ecma_op_object_put (obj_p, str_idx_p, args[arg_index], true ),
1710+ ret_value);
1711+
1712+ ECMA_FINALIZE (put_value);
1713+ ecma_deref_ecma_string (str_idx_p);
1714+ }
1715+
1716+ /* 16. */
1717+ if (ecma_is_completion_value_empty (ret_value))
1718+ {
1719+ ECMA_TRY_CATCH (set_length_value,
1720+ ecma_builtin_array_prototype_helper_set_length (obj_p, new_len),
1721+ ret_value);
1722+
1723+ ECMA_FINALIZE (set_length_value);
1724+ }
1725+
1726+ if (ecma_is_completion_value_empty (ret_value))
1727+ {
1728+ ret_value = new_array;
1729+ }
1730+ else
1731+ {
1732+ ecma_free_completion_value (new_array);
1733+ }
1734+
1735+ ECMA_OP_TO_NUMBER_FINALIZE (len_number);
1736+ ECMA_FINALIZE (len_value);
1737+ ecma_deref_ecma_string (length_magic_string_p);
1738+ ECMA_FINALIZE (obj_this);
1739+
1740+ return ret_value;
1741+ } /* ecma_builtin_array_prototype_object_splice */
1742+
14381743/* *
14391744 * @}
14401745 * @}
0 commit comments