Skip to content

Commit

Permalink
improve polyfill of stable sort
Browse files Browse the repository at this point in the history
  • Loading branch information
zloirock committed Jun 4, 2021
1 parent 98555de commit a56b289
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 7 deletions.
32 changes: 28 additions & 4 deletions packages/core-js/internals/array-sort.js
Expand Up @@ -4,6 +4,10 @@ var toObject = require('../internals/to-object');
var toLength = require('../internals/to-length');
var fails = require('../internals/fails');
var arrayMethodIsStrict = require('../internals/array-method-is-strict');
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 test = [];
var nativeSort = test.sort;
Expand All @@ -21,6 +25,12 @@ var FAILS_ON_NULL = fails(function () {
var STRICT_METHOD = arrayMethodIsStrict('sort');

var STABLE_SORT = !fails(function () {
// feature detection can be too slow, so check engines versions
if (V8) return V8 < 70;
if (FF && FF > 3) return;
if (IE_OR_EDGE) return true;
if (WEBKIT) return WEBKIT < 603;

var result = '';
var code, chr, value, index;

Expand Down Expand Up @@ -53,14 +63,28 @@ var FORCED = FAILS_ON_UNDEFINED || !FAILS_ON_NULL || !STRICT_METHOD || !STABLE_S
var mergeSort = function (array, comparefn) {
var length = array.length;
var middle = floor(length / 2);
if (length < 2) return array;
return merge(
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 && sortCompare(array[j - 1], element, comparefn) > 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;
Expand All @@ -78,9 +102,8 @@ var merge = function (left, right, comparefn) {
};

var sortCompare = function (x, y, comparefn) {
if (x === undefined && y === undefined) return 0;
if (x === undefined) return 1;
if (y === undefined) return -1;
if (x === undefined) return 1;
if (comparefn !== undefined) {
return +comparefn(x, y) || 0;
} return String(x) > String(y) ? 1 : -1;
Expand All @@ -103,6 +126,7 @@ module.exports = FORCED ? function sort(comparefn) {
if (index in array) items.push(array[index]);
}

// TODO: use something more complex like timsort?
items = mergeSort(items, comparefn);
itemsLength = items.length;
index = 0;
Expand Down
5 changes: 5 additions & 0 deletions packages/core-js/internals/engine-ff-version.js
@@ -0,0 +1,5 @@
var userAgent = require('../internals/engine-user-agent');

var firefox = userAgent.match(/firefox\/(\d+)/i);

module.exports = !!firefox && +firefox[1];
3 changes: 3 additions & 0 deletions packages/core-js/internals/engine-is-ie-or-edge.js
@@ -0,0 +1,3 @@
var UA = require('../internals/engine-user-agent');

module.exports = /MSIE|Trident/.test(UA);
5 changes: 5 additions & 0 deletions packages/core-js/internals/engine-webkit-version.js
@@ -0,0 +1,5 @@
var userAgent = require('../internals/engine-user-agent');

var webkit = userAgent.match(/AppleWebKit\/(\d+)\./);

module.exports = !!webkit && +webkit[1];
Expand Up @@ -2,14 +2,13 @@
var IS_PURE = require('../internals/is-pure');
var global = require('../internals/global');
var fails = require('../internals/fails');
var userAgent = require('../internals/engine-user-agent');
var WEBKIT = require('../internals/engine-webkit-version');

// Forced replacement object prototype accessors methods
module.exports = IS_PURE || !fails(function () {
// This feature detection crashes old WebKit
// https://github.com/zloirock/core-js/issues/232
var webkit = userAgent.match(/AppleWebKit\/(\d+)\./);
if (webkit && +webkit[1] < 535) return;
if (WEBKIT && WEBKIT < 535) return;
var key = Math.random();
// In FF throws only define methods
// eslint-disable-next-line no-undef, no-useless-call -- required for testing
Expand Down
10 changes: 10 additions & 0 deletions packages/core-js/modules/es.typed-array.sort.js
Expand Up @@ -2,11 +2,21 @@
var ArrayBufferViewCore = require('../internals/array-buffer-view-core');
var fails = require('../internals/fails');
var $sort = 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 STABLE_SORT = !fails(function () {
// feature detection can be too slow, so check engines versions
if (V8) return V8 < 73;
if (FF) return FF < 67;
if (IE_OR_EDGE) return true;
if (WEBKIT) return WEBKIT < 602;

// eslint-disable-next-line es/no-typed-arrays -- required for testing
var array = new Uint16Array(516);
var expected = Array(516);
Expand Down

0 comments on commit a56b289

Please sign in to comment.