@@ -770,6 +770,331 @@ ecma_builtin_array_prototype_object_last_index_of (ecma_value_t this_arg, /**< t
770
770
return ret_value;
771
771
} /* ecma_builtin_array_prototype_object_last_index_of */
772
772
773
+ /* *
774
+ * SortCompare abstract method
775
+ *
776
+ * See also:
777
+ * ECMA-262 v5, 15.4.4.11
778
+ *
779
+ * @return completion value
780
+ * Returned value must be freed with ecma_free_completion_value.
781
+ */
782
+ static ecma_completion_value_t
783
+ ecma_builtin_array_prototype_object_sort_compare_helper (ecma_value_t j, /* *< left value */
784
+ ecma_value_t k, /* *< right value */
785
+ ecma_value_t comparefn) /* *< compare function */
786
+ {
787
+ /*
788
+ * ECMA-262 v5, 15.4.4.11 NOTE1: Because non-existent property values always
789
+ * compare greater than undefined property values, and undefined always
790
+ * compares greater than any other value, undefined property values always
791
+ * sort to the end of the result, followed by non-existent property values.
792
+ */
793
+ ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
794
+ ecma_number_t *result = ecma_alloc_number ();
795
+
796
+ bool j_is_undef = ecma_is_value_undefined (j);
797
+ bool k_is_undef = ecma_is_value_undefined (k);
798
+
799
+ if (j_is_undef)
800
+ {
801
+ if (k_is_undef)
802
+ {
803
+ *result = ecma_int32_to_number (0 );
804
+ }
805
+ else
806
+ {
807
+ *result = ecma_int32_to_number (1 );
808
+ }
809
+ }
810
+ else
811
+ {
812
+ if (k_is_undef)
813
+ {
814
+ *result = ecma_int32_to_number (-1 );
815
+ }
816
+ else
817
+ {
818
+ if (ecma_is_value_undefined (comparefn))
819
+ {
820
+ /* Default comparison when no comparefn is passed. */
821
+ ECMA_TRY_CATCH (j_value, ecma_op_to_string (j), ret_value);
822
+ ECMA_TRY_CATCH (k_value, ecma_op_to_string (k), ret_value);
823
+ ecma_string_t * j_str_p = ecma_get_string_from_completion_value (j_value);
824
+ ecma_string_t * k_str_p = ecma_get_string_from_completion_value (k_value);
825
+
826
+ if (ecma_compare_ecma_strings_relational (j_str_p, k_str_p))
827
+ {
828
+ *result = ecma_int32_to_number (-1 );
829
+ }
830
+ else if (!ecma_compare_ecma_strings (j_str_p, k_str_p))
831
+ {
832
+ *result = ecma_int32_to_number (1 );
833
+ }
834
+ else
835
+ {
836
+ *result = ecma_int32_to_number (0 );
837
+ }
838
+
839
+ ECMA_FINALIZE (k_value);
840
+ ECMA_FINALIZE (j_value);
841
+ }
842
+ else
843
+ {
844
+ /*
845
+ * comparefn, if not undefined, will always contain a callable function object.
846
+ * We checked this previously, before this function was called.
847
+ */
848
+ JERRY_ASSERT (ecma_op_is_callable (comparefn));
849
+ ecma_object_t * comparefn_obj_p = ecma_get_object_from_value (comparefn);
850
+
851
+ ecma_value_t compare_args[] = {j, k};
852
+
853
+ ECMA_TRY_CATCH (call_value,
854
+ ecma_op_function_call (comparefn_obj_p,
855
+ ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED),
856
+ compare_args,
857
+ 2 ),
858
+ ret_value);
859
+
860
+ if (!ecma_is_value_number (call_value))
861
+ {
862
+ ECMA_OP_TO_NUMBER_TRY_CATCH (ret_num, call_value, ret_value);
863
+ ecma_number_t *num_p = ecma_alloc_number ();
864
+ *num_p = ret_num;
865
+ ret_value = ecma_make_number_value (num_p);
866
+ ECMA_OP_TO_NUMBER_FINALIZE (ret_num);
867
+ }
868
+ else
869
+ {
870
+ ecma_number_t *number = ecma_get_number_from_value (call_value);
871
+ if (*number < ECMA_NUMBER_ZERO)
872
+ {
873
+ *result = ecma_int32_to_number (-1 );
874
+ }
875
+ else if (*number > ECMA_NUMBER_ZERO)
876
+ {
877
+ *result = ecma_int32_to_number (1 );
878
+ }
879
+ else
880
+ {
881
+ *result = ecma_int32_to_number (0 );
882
+ }
883
+ }
884
+
885
+ ECMA_FINALIZE (call_value);
886
+ }
887
+ }
888
+ }
889
+
890
+ if (ecma_is_completion_value_empty (ret_value))
891
+ {
892
+ ret_value = ecma_make_normal_completion_value (ecma_make_number_value (result));
893
+ }
894
+ else
895
+ {
896
+ ecma_dealloc_number (result);
897
+ }
898
+
899
+ return ret_value;
900
+ } /* ecma_builtin_array_prototype_object_sort_compare_helper */
901
+
902
+ /* *
903
+ * Shifting an item in the heap data structure
904
+ *
905
+ * @return completion value
906
+ * Returned value must be freed with ecma_free_completion_value.
907
+ */
908
+ static ecma_completion_value_t
909
+ ecma_builtin_array_prototype_object_array_to_heap_helper (ecma_value_t array[], /* *< heap data array */
910
+ int index, /* *< current item index */
911
+ int right, /* *< right index is a maximum index */
912
+ ecma_value_t comparefn) /* *< compare function */
913
+ {
914
+ ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
915
+ int child = 2 * index;
916
+ ecma_value_t swap = array[index];
917
+
918
+ while (child < right && ecma_is_completion_value_empty (ret_value))
919
+ {
920
+ ECMA_TRY_CATCH (compare_value,
921
+ ecma_builtin_array_prototype_object_sort_compare_helper (array[child],
922
+ array[child + 1 ],
923
+ comparefn),
924
+ ret_value);
925
+ JERRY_ASSERT (ecma_is_value_number (compare_value));
926
+
927
+ if ((*ecma_get_number_from_value (compare_value) < ECMA_NUMBER_ZERO))
928
+ {
929
+ child++;
930
+ }
931
+
932
+ ECMA_TRY_CATCH (inner_compare_value,
933
+ ecma_builtin_array_prototype_object_sort_compare_helper (array[child],
934
+ swap,
935
+ comparefn),
936
+ ret_value);
937
+ JERRY_ASSERT (ecma_is_value_number (inner_compare_value));
938
+
939
+ if (*ecma_get_number_from_value (inner_compare_value) <= ECMA_NUMBER_ZERO)
940
+ {
941
+ /* Break from loop */
942
+ ret_value = ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_UNDEFINED);
943
+ }
944
+ else
945
+ {
946
+ array[child / 2 ] = array[child];
947
+ child = (child == 0 ) ? 1 : child * 2 ;
948
+ }
949
+
950
+ ECMA_FINALIZE (inner_compare_value);
951
+ ECMA_FINALIZE (compare_value);
952
+ }
953
+
954
+ if (ecma_is_completion_value_empty (ret_value) || ecma_is_completion_value_normal (ret_value))
955
+ {
956
+ array[child / 2 ] = swap;
957
+ }
958
+
959
+ if (ecma_is_completion_value_empty (ret_value))
960
+ {
961
+ ret_value = ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_UNDEFINED);
962
+ }
963
+
964
+ return ret_value;
965
+ } /* ecma_builtin_array_prototype_object_array_to_heap_helper */
966
+
967
+ /* *
968
+ * Heapsort function
969
+ *
970
+ * @return completion value
971
+ * Returned value must be freed with ecma_free_completion_value.
972
+ */
973
+ static ecma_completion_value_t
974
+ ecma_builtin_array_prototype_object_array_heap_sort_helper (ecma_value_t array[], /* *< array to sort */
975
+ int right, /* *< right index */
976
+ ecma_value_t comparefn) /* *< compare function */
977
+ {
978
+ ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
979
+
980
+ for (int i = right / 2 ; i >= 0 && ecma_is_completion_value_empty (ret_value); i--)
981
+ {
982
+ ECMA_TRY_CATCH (value,
983
+ ecma_builtin_array_prototype_object_array_to_heap_helper (array,
984
+ i,
985
+ right,
986
+ comparefn),
987
+ ret_value);
988
+ ECMA_FINALIZE (value);
989
+ }
990
+
991
+ for (int i = right; i > 0 && ecma_is_completion_value_empty (ret_value); i--)
992
+ {
993
+ ecma_value_t swap = array[0 ];
994
+ array[0 ] = array[i];
995
+ array[i] = swap;
996
+ ECMA_TRY_CATCH (value,
997
+ ecma_builtin_array_prototype_object_array_to_heap_helper (array,
998
+ 0 ,
999
+ i - 1 ,
1000
+ comparefn),
1001
+ ret_value);
1002
+ ECMA_FINALIZE (value);
1003
+ }
1004
+
1005
+ return ret_value;
1006
+ } /* ecma_builtin_array_prototype_object_array_heap_sort_helper */
1007
+
1008
+ /* *
1009
+ * The Array.prototype object's 'sort' routine
1010
+ *
1011
+ * See also:
1012
+ * ECMA-262 v5, 15.4.4.11
1013
+ *
1014
+ * @return completion value
1015
+ * Returned value must be freed with ecma_free_completion_value.
1016
+ */
1017
+ static ecma_completion_value_t
1018
+ ecma_builtin_array_prototype_object_sort (ecma_value_t this_arg, /* *< this argument */
1019
+ ecma_value_t arg1) /* *< comparefn */
1020
+ {
1021
+ /* Check if the provided compare function is callable. */
1022
+ if (!ecma_is_value_undefined (arg1) && !ecma_op_is_callable (arg1))
1023
+ {
1024
+ return ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE));
1025
+ }
1026
+
1027
+ ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
1028
+
1029
+ ECMA_TRY_CATCH (obj_this,
1030
+ ecma_op_to_object (this_arg),
1031
+ ret_value);
1032
+
1033
+ ecma_object_t *obj_p = ecma_get_object_from_value (obj_this);
1034
+ ecma_string_t *magic_string_length_p = ecma_get_magic_string (ECMA_MAGIC_STRING_LENGTH);
1035
+
1036
+ ECMA_TRY_CATCH (len_value,
1037
+ ecma_op_object_get (obj_p, magic_string_length_p),
1038
+ ret_value);
1039
+
1040
+ ECMA_OP_TO_NUMBER_TRY_CATCH (len_number, len_value, ret_value);
1041
+
1042
+ uint32_t len = ecma_number_to_uint32 (len_number);
1043
+
1044
+ MEM_DEFINE_LOCAL_ARRAY (values_buffer, len, ecma_value_t );
1045
+ uint32_t copied_num = 0 ;
1046
+
1047
+ /* Copy unsorted array into a native c array. */
1048
+ for (uint32_t index = 0 ; index < len && ecma_is_completion_value_empty (ret_value); index++)
1049
+ {
1050
+ ecma_string_t * index_string_p = ecma_new_ecma_string_from_uint32 (index);
1051
+ ECMA_TRY_CATCH (index_value, ecma_op_object_get (obj_p, index_string_p), ret_value);
1052
+
1053
+ values_buffer[index] = ecma_copy_value (index_value, true );
1054
+ copied_num++;
1055
+
1056
+ ECMA_FINALIZE (index_value);
1057
+ ecma_deref_ecma_string (index_string_p);
1058
+ }
1059
+
1060
+ JERRY_ASSERT (copied_num == len || !ecma_is_completion_value_empty (ret_value));
1061
+
1062
+ /* Sorting. */
1063
+ if (len > 1 && ecma_is_completion_value_empty (ret_value))
1064
+ {
1065
+ ECMA_TRY_CATCH (sort_value,
1066
+ ecma_builtin_array_prototype_object_array_heap_sort_helper (values_buffer,
1067
+ (int )(len - 1 ),
1068
+ arg1),
1069
+ ret_value);
1070
+ ECMA_FINALIZE (sort_value);
1071
+ }
1072
+
1073
+ if (ecma_is_completion_value_empty (ret_value))
1074
+ {
1075
+ /* Casting len to ecma_length_t may overflow, but since ecma_length_t is still at lest 16 bits long,
1076
+ with an array of that size, we would run out of memory way before this happens. */
1077
+ JERRY_ASSERT ((ecma_length_t ) len == len);
1078
+ /* Copy the sorted array into a new array. */
1079
+ ret_value = ecma_op_create_array_object (values_buffer, (ecma_length_t ) len, false );
1080
+ }
1081
+
1082
+ /* Free values that were copied to the local array. */
1083
+ for (uint32_t index = 0 ; index < copied_num; index++)
1084
+ {
1085
+ ecma_free_value (values_buffer[index], true );
1086
+ }
1087
+
1088
+ MEM_FINALIZE_LOCAL_ARRAY (values_buffer);
1089
+
1090
+ ECMA_OP_TO_NUMBER_FINALIZE (len_number);
1091
+ ECMA_FINALIZE (len_value);
1092
+ ecma_deref_ecma_string (magic_string_length_p);
1093
+ ECMA_FINALIZE (obj_this);
1094
+
1095
+ return ret_value;
1096
+ } /* ecma_builtin_array_prototype_object_sort */
1097
+
773
1098
/* *
774
1099
* The Array.prototype object's 'shift' routine
775
1100
*
0 commit comments