|
14 | 14 | */
|
15 | 15 |
|
16 | 16 | #include "ecma-alloc.h"
|
| 17 | +#include "ecma-array-object.h" |
17 | 18 | #include "ecma-builtins.h"
|
18 | 19 | #include "ecma-comparison.h"
|
19 | 20 | #include "ecma-conversion.h"
|
@@ -702,6 +703,162 @@ ecma_builtin_array_prototype_object_unshift (ecma_value_t this_arg, /**< this ar
|
702 | 703 | return ret_value;
|
703 | 704 | } /* ecma_builtin_array_prototype_object_unshift */
|
704 | 705 |
|
| 706 | +/** |
| 707 | + * The Array.prototype object's 'slice' routine |
| 708 | + * |
| 709 | + * See also: |
| 710 | + * ECMA-262 v5, 15.4.4.10 |
| 711 | + * |
| 712 | + * @return completion value |
| 713 | + * Returned value must be freed with ecma_free_completion_value. |
| 714 | + */ |
| 715 | +static ecma_completion_value_t |
| 716 | +ecma_builtin_array_prototype_object_slice (ecma_value_t this_arg, /**< 'this' argument */ |
| 717 | + ecma_value_t arg1, /**< start */ |
| 718 | + ecma_value_t arg2) /**< end */ |
| 719 | +{ |
| 720 | + ecma_completion_value_t ret_value = ecma_make_empty_completion_value (); |
| 721 | + |
| 722 | + /* 1. */ |
| 723 | + ECMA_TRY_CATCH (obj_this, |
| 724 | + ecma_op_to_object (this_arg), |
| 725 | + ret_value); |
| 726 | + |
| 727 | + ecma_object_t* obj_p = ecma_get_object_from_value (obj_this); |
| 728 | + ecma_string_t* length_magic_string_p = ecma_get_magic_string (ECMA_MAGIC_STRING_LENGTH); |
| 729 | + |
| 730 | + ECMA_TRY_CATCH (len_value, |
| 731 | + ecma_op_object_get (obj_p, length_magic_string_p), |
| 732 | + ret_value); |
| 733 | + |
| 734 | + /* 3. */ |
| 735 | + ECMA_OP_TO_NUMBER_TRY_CATCH (len_number, len_value, ret_value); |
| 736 | + |
| 737 | + /* 4. */ |
| 738 | + const uint32_t len = ecma_number_to_uint32 (len_number); |
| 739 | + |
| 740 | + uint32_t start = 0, end = len; |
| 741 | + |
| 742 | + /* 5. */ |
| 743 | + ECMA_OP_TO_NUMBER_TRY_CATCH (start_num, arg1, ret_value); |
| 744 | + int32_t relative_start = ecma_number_to_int32 (start_num); |
| 745 | + |
| 746 | + /* 6. */ |
| 747 | + if (relative_start < 0) |
| 748 | + { |
| 749 | + uint32_t start_abs = (uint32_t) -relative_start; |
| 750 | + |
| 751 | + if (start_abs > len) |
| 752 | + { |
| 753 | + start = 0; |
| 754 | + } |
| 755 | + else |
| 756 | + { |
| 757 | + start = len - start_abs; |
| 758 | + } |
| 759 | + } |
| 760 | + else |
| 761 | + { |
| 762 | + start = (uint32_t) relative_start; |
| 763 | + if (start > len) |
| 764 | + { |
| 765 | + start = len; |
| 766 | + } |
| 767 | + } |
| 768 | + |
| 769 | + /* 7. */ |
| 770 | + if (ecma_is_value_undefined (arg2)) |
| 771 | + { |
| 772 | + end = len; |
| 773 | + } |
| 774 | + else |
| 775 | + { |
| 776 | + /* 7. part 2*/ |
| 777 | + ECMA_OP_TO_NUMBER_TRY_CATCH (end_num, arg2, ret_value) |
| 778 | + int32_t relative_end = ecma_number_to_int32 (end_num); |
| 779 | + |
| 780 | + if (relative_end < 0) |
| 781 | + { |
| 782 | + uint32_t end_abs = (uint32_t) -relative_end; |
| 783 | + |
| 784 | + if (end_abs > len) |
| 785 | + { |
| 786 | + end = 0; |
| 787 | + } |
| 788 | + else |
| 789 | + { |
| 790 | + end = len - end_abs; |
| 791 | + } |
| 792 | + } |
| 793 | + else |
| 794 | + { |
| 795 | + end = (uint32_t) relative_end; |
| 796 | + if (end > len) |
| 797 | + { |
| 798 | + end = len; |
| 799 | + } |
| 800 | + } |
| 801 | + |
| 802 | + ECMA_OP_TO_NUMBER_FINALIZE (end_num); |
| 803 | + } |
| 804 | + |
| 805 | + ECMA_OP_TO_NUMBER_FINALIZE (start_num); |
| 806 | + |
| 807 | + JERRY_ASSERT (start <= len && end <= len); |
| 808 | + |
| 809 | + ecma_completion_value_t new_array = ecma_op_create_array_object (0, 0, false); |
| 810 | + ecma_object_t *new_array_p = ecma_get_object_from_completion_value (new_array); |
| 811 | + |
| 812 | + /* 9. */ |
| 813 | + uint32_t n = 0; |
| 814 | + |
| 815 | + /* 10. */ |
| 816 | + for (uint32_t k = start; k < end && ecma_is_completion_value_empty (ret_value); k++, n++) |
| 817 | + { |
| 818 | + /* 10.a */ |
| 819 | + ecma_string_t *curr_idx_str_p = ecma_new_ecma_string_from_uint32 (k); |
| 820 | + |
| 821 | + /* 10.c */ |
| 822 | + if (ecma_op_object_get_property (obj_p, curr_idx_str_p) != NULL) |
| 823 | + { |
| 824 | + /* 10.c.i */ |
| 825 | + ECMA_TRY_CATCH (get_value, ecma_op_object_get (obj_p, curr_idx_str_p), ret_value); |
| 826 | + |
| 827 | + ecma_string_t *to_idx_str_p = ecma_new_ecma_string_from_uint32 (n); |
| 828 | + /* |
| 829 | + * 10.c.ii |
| 830 | + * Using [[Put]] is equivalent to using [[DefineOwnProperty]] as specified the standard, |
| 831 | + * so we use [[Put]] instead for simplicity. No need for a try-catch block since it is called |
| 832 | + * with is_throw = false. |
| 833 | + */ |
| 834 | + ecma_completion_value_t put_comp_value = ecma_op_object_put (new_array_p, to_idx_str_p, get_value, false); |
| 835 | + JERRY_ASSERT (ecma_is_completion_value_normal (put_comp_value)); |
| 836 | + ecma_free_completion_value (put_comp_value); |
| 837 | + ecma_deref_ecma_string (to_idx_str_p); |
| 838 | + |
| 839 | + ECMA_FINALIZE (get_value); |
| 840 | + } |
| 841 | + |
| 842 | + ecma_deref_ecma_string (curr_idx_str_p); |
| 843 | + } |
| 844 | + |
| 845 | + if (ecma_is_completion_value_empty (ret_value)) |
| 846 | + { |
| 847 | + ret_value = new_array; |
| 848 | + } |
| 849 | + else |
| 850 | + { |
| 851 | + ecma_free_completion_value (new_array); |
| 852 | + } |
| 853 | + |
| 854 | + ECMA_OP_TO_NUMBER_FINALIZE (len_number); |
| 855 | + ECMA_FINALIZE (len_value); |
| 856 | + ecma_deref_ecma_string (length_magic_string_p); |
| 857 | + ECMA_FINALIZE (obj_this); |
| 858 | + |
| 859 | + return ret_value; |
| 860 | +} /* ecma_builtin_array_prototype_object_slice */ |
| 861 | + |
705 | 862 | /**
|
706 | 863 | * @}
|
707 | 864 | * @}
|
|
0 commit comments