-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #941 from zloirock/stable-sort
close #769
- Loading branch information
Showing
14 changed files
with
548 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
// TODO: use something more complex like timsort? | ||
var floor = Math.floor; | ||
|
||
var mergeSort = function (array, comparefn) { | ||
var length = array.length; | ||
var middle = floor(length / 2); | ||
return length < 8 ? insertionSort(array, comparefn) : merge( | ||
mergeSort(array.slice(0, middle), comparefn), | ||
mergeSort(array.slice(middle), comparefn), | ||
comparefn | ||
); | ||
}; | ||
|
||
var insertionSort = function (array, comparefn) { | ||
var length = array.length; | ||
var i = 1; | ||
var element, j; | ||
|
||
while (i < length) { | ||
j = i; | ||
element = array[i]; | ||
while (j && comparefn(array[j - 1], element) > 0) { | ||
array[j] = array[--j]; | ||
} | ||
if (j !== i++) array[j] = element; | ||
} return array; | ||
}; | ||
|
||
var merge = function (left, right, comparefn) { | ||
var llength = left.length; | ||
var rlength = right.length; | ||
var lindex = 0; | ||
var rindex = 0; | ||
var result = []; | ||
|
||
while (lindex < llength || rindex < rlength) { | ||
if (lindex < llength && rindex < rlength) { | ||
result.push(comparefn(left[lindex], right[rindex]) <= 0 ? left[lindex++] : right[rindex++]); | ||
} else { | ||
result.push(lindex < llength ? left[lindex++] : right[rindex++]); | ||
} | ||
} return result; | ||
}; | ||
|
||
module.exports = mergeSort; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
var userAgent = require('../internals/engine-user-agent'); | ||
|
||
var firefox = userAgent.match(/firefox\/(\d+)/i); | ||
|
||
module.exports = !!firefox && +firefox[1]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
var UA = require('../internals/engine-user-agent'); | ||
|
||
module.exports = /MSIE|Trident/.test(UA); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
var userAgent = require('../internals/engine-user-agent'); | ||
|
||
var webkit = userAgent.match(/AppleWebKit\/(\d+)\./); | ||
|
||
module.exports = !!webkit && +webkit[1]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,86 @@ | ||
'use strict'; | ||
var ArrayBufferViewCore = require('../internals/array-buffer-view-core'); | ||
var global = require('../internals/global'); | ||
var fails = require('../internals/fails'); | ||
var aFunction = require('../internals/a-function'); | ||
var toLength = require('../internals/to-length'); | ||
var internalSort = require('../internals/array-sort'); | ||
var FF = require('../internals/engine-ff-version'); | ||
var IE_OR_EDGE = require('../internals/engine-is-ie-or-edge'); | ||
var V8 = require('../internals/engine-v8-version'); | ||
var WEBKIT = require('../internals/engine-webkit-version'); | ||
|
||
var aTypedArray = ArrayBufferViewCore.aTypedArray; | ||
var exportTypedArrayMethod = ArrayBufferViewCore.exportTypedArrayMethod; | ||
var $sort = [].sort; | ||
var Uint16Array = global.Uint16Array; | ||
var nativeSort = Uint16Array && Uint16Array.prototype.sort; | ||
|
||
// WebKit | ||
var ACCEPT_INCORRECT_ARGUMENTS = !!nativeSort && !fails(function () { | ||
var array = new Uint16Array(2); | ||
array.sort(null); | ||
array.sort({}); | ||
}); | ||
|
||
var STABLE_SORT = !!nativeSort && !fails(function () { | ||
// feature detection can be too slow, so check engines versions | ||
if (V8) return V8 < 74; | ||
if (FF) return FF < 67; | ||
if (IE_OR_EDGE) return true; | ||
if (WEBKIT) return WEBKIT < 602; | ||
|
||
var array = new Uint16Array(516); | ||
var expected = Array(516); | ||
var index, mod; | ||
|
||
for (index = 0; index < 516; index++) { | ||
mod = index % 4; | ||
array[index] = 515 - index; | ||
expected[index] = index - 2 * mod + 3; | ||
} | ||
|
||
array.sort(function (a, b) { | ||
return (a / 4 | 0) - (b / 4 | 0); | ||
}); | ||
|
||
for (index = 0; index < 516; index++) { | ||
if (array[index] !== expected[index]) return true; | ||
} | ||
}); | ||
|
||
var getSortCompare = function (comparefn) { | ||
return function (x, y) { | ||
if (comparefn !== undefined) return +comparefn(x, y) || 0; | ||
// eslint-disable-next-line no-self-compare -- NaN check | ||
if (y !== y) return -1; | ||
// eslint-disable-next-line no-self-compare -- NaN check | ||
if (x !== x) return 1; | ||
if (x === 0 && y === 0) return 1 / x > 0 && 1 / y < 0 ? 1 : -1; | ||
return x > y; | ||
}; | ||
}; | ||
|
||
// `%TypedArray%.prototype.sort` method | ||
// https://tc39.es/ecma262/#sec-%typedarray%.prototype.sort | ||
exportTypedArrayMethod('sort', function sort(comparefn) { | ||
return $sort.call(aTypedArray(this), comparefn); | ||
}); | ||
var array = this; | ||
if (comparefn !== undefined) aFunction(comparefn); | ||
if (STABLE_SORT) return nativeSort.call(array, comparefn); | ||
|
||
aTypedArray(array); | ||
var arrayLength = toLength(array.length); | ||
var items = Array(arrayLength); | ||
var index; | ||
|
||
for (index = 0; index < arrayLength; index++) { | ||
items[index] = array[index]; | ||
} | ||
|
||
items = internalSort(array, getSortCompare(comparefn)); | ||
|
||
for (index = 0; index < arrayLength; index++) { | ||
array[index] = items[index]; | ||
} | ||
|
||
return array; | ||
}, !STABLE_SORT || ACCEPT_INCORRECT_ARGUMENTS); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.