2
2
var $ = require ( '../internals/export' ) ;
3
3
var aFunction = require ( '../internals/a-function' ) ;
4
4
var toObject = require ( '../internals/to-object' ) ;
5
+ var toLength = require ( '../internals/to-length' ) ;
5
6
var fails = require ( '../internals/fails' ) ;
7
+ var internalSort = require ( '../internals/array-sort' ) ;
6
8
var arrayMethodIsStrict = require ( '../internals/array-method-is-strict' ) ;
9
+ var FF = require ( '../internals/engine-ff-version' ) ;
10
+ var IE_OR_EDGE = require ( '../internals/engine-is-ie-or-edge' ) ;
11
+ var V8 = require ( '../internals/engine-v8-version' ) ;
12
+ var WEBKIT = require ( '../internals/engine-webkit-version' ) ;
7
13
8
14
var test = [ ] ;
9
15
var nativeSort = test . sort ;
@@ -19,14 +25,77 @@ var FAILS_ON_NULL = fails(function () {
19
25
// Old WebKit
20
26
var STRICT_METHOD = arrayMethodIsStrict ( 'sort' ) ;
21
27
22
- var FORCED = FAILS_ON_UNDEFINED || ! FAILS_ON_NULL || ! STRICT_METHOD ;
28
+ var STABLE_SORT = ! fails ( function ( ) {
29
+ // feature detection can be too slow, so check engines versions
30
+ if ( V8 ) return V8 < 70 ;
31
+ if ( FF && FF > 3 ) return ;
32
+ if ( IE_OR_EDGE ) return true ;
33
+ if ( WEBKIT ) return WEBKIT < 603 ;
34
+
35
+ var result = '' ;
36
+ var code , chr , value , index ;
37
+
38
+ // generate an array with more 512 elements (Chakra and old V8 fails only in this case)
39
+ for ( code = 65 ; code < 76 ; code ++ ) {
40
+ chr = String . fromCharCode ( code ) ;
41
+
42
+ switch ( code ) {
43
+ case 66 : case 69 : case 70 : case 72 : value = 3 ; break ;
44
+ case 68 : case 71 : value = 4 ; break ;
45
+ default : value = 2 ;
46
+ }
47
+
48
+ for ( index = 0 ; index < 47 ; index ++ ) {
49
+ test . push ( { k : chr + index , v : value } ) ;
50
+ }
51
+ }
52
+
53
+ test . sort ( function ( a , b ) { return b . v - a . v ; } ) ;
54
+
55
+ for ( index = 0 ; index < test . length ; index ++ ) {
56
+ chr = test [ index ] . k . charAt ( 0 ) ;
57
+ if ( result . charAt ( result . length - 1 ) !== chr ) result += chr ;
58
+ }
59
+
60
+ return result !== 'DGBEFHACIJK' ;
61
+ } ) ;
62
+
63
+ var FORCED = FAILS_ON_UNDEFINED || ! FAILS_ON_NULL || ! STRICT_METHOD || ! STABLE_SORT ;
64
+
65
+ var getSortCompare = function ( comparefn ) {
66
+ return function ( x , y ) {
67
+ if ( y === undefined ) return - 1 ;
68
+ if ( x === undefined ) return 1 ;
69
+ if ( comparefn !== undefined ) return + comparefn ( x , y ) || 0 ;
70
+ return String ( x ) > String ( y ) ? 1 : - 1 ;
71
+ } ;
72
+ } ;
23
73
24
74
// `Array.prototype.sort` method
25
75
// https://tc39.es/ecma262/#sec-array.prototype.sort
26
76
$ ( { target : 'Array' , proto : true , forced : FORCED } , {
27
77
sort : function sort ( comparefn ) {
28
- return comparefn === undefined
29
- ? nativeSort . call ( toObject ( this ) )
30
- : nativeSort . call ( toObject ( this ) , aFunction ( comparefn ) ) ;
78
+ if ( comparefn !== undefined ) aFunction ( comparefn ) ;
79
+
80
+ var array = toObject ( this ) ;
81
+
82
+ if ( STABLE_SORT ) return comparefn === undefined ? nativeSort . call ( array ) : nativeSort . call ( array , comparefn ) ;
83
+
84
+ var items = [ ] ;
85
+ var arrayLength = toLength ( array . length ) ;
86
+ var itemsLength , index ;
87
+
88
+ for ( index = 0 ; index < arrayLength ; index ++ ) {
89
+ if ( index in array ) items . push ( array [ index ] ) ;
90
+ }
91
+
92
+ items = internalSort ( items , getSortCompare ( comparefn ) ) ;
93
+ itemsLength = items . length ;
94
+ index = 0 ;
95
+
96
+ while ( index < itemsLength ) array [ index ] = items [ index ++ ] ;
97
+ while ( index < arrayLength ) delete array [ index ++ ] ;
98
+
99
+ return array ;
31
100
}
32
101
} ) ;
0 commit comments