Skip to content

Commit

Permalink
add %TypedArray%#uniqueBy method
Browse files Browse the repository at this point in the history
  • Loading branch information
zloirock committed Feb 17, 2021
1 parent 05fccd8 commit b369faf
Show file tree
Hide file tree
Showing 18 changed files with 117 additions and 83 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
- `Array#findLastIndex`
- `%TypedArray%#findLast`
- `%TypedArray%#findLastIndex`
- Added `%TypedArray%#uniqueBy` method for [array deduplication stage 1 proposal](https://github.com/tc39/proposal-array-unique)
- `%TypedArray%#uniqueBy`
- Dropped `ToLength` detection from array methods feature detection which could cause hanging FF11-21 and some versions of old WebKit, [#764](https://github.com/zloirock/core-js/issues/764)
- Minified bundle from `core-js-bundle` uses `terser` instead of `uglify-js`

Expand Down
56 changes: 17 additions & 39 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1468,10 +1468,13 @@ class [
Uint32Array,
Float32Array,
Float64Array,
] {
] extends %TypedArray% {
constructor(length: number): %TypedArray%;
constructor(object: %TypedArray% | Iterable | ArrayLike): %TypedArray%;
constructor(buffer: ArrayBuffer, byteOffset?: number, length?: number): %TypedArray%;
constructor(buffer: ArrayBuffer, byteOffset?: number, length?: number): %TypedArray%
}

class %TypedArray% {
copyWithin(target: number, start: number, end?: number): this;
every(callbackfn: (value: number, index: number, target: %TypedArray%) => boolean, thisArg?: any): boolean;
fill(value: number, start?: number, end?: number): this;
Expand Down Expand Up @@ -1787,17 +1790,7 @@ class Array {
at(index: int): any;
}
class [
Int8Array,
Uint8Array,
Uint8ClampedArray,
Int16Array,
Uint16Array,
Int32Array,
Uint32Array,
Float32Array,
Float64Array,
] {
class %TypedArray% {
at(index: int): any;
}
```
Expand Down Expand Up @@ -2402,41 +2395,36 @@ class Array {
filterOut(callbackfn: (value: any, index: number, target: any) => boolean, thisArg?: any): Array<mixed>;
}

class [
Int8Array,
Uint8Array,
Uint8ClampedArray,
Int16Array,
Uint16Array,
Int32Array,
Uint32Array,
Float32Array,
Float64Array,
] {
class %TypedArray% {
filterOut(callbackfn: (value: number, index: number, target: %TypedArray%) => boolean, thisArg?: any): %TypedArray%;
}
```
[*CommonJS entry points:*](#commonjs-api)
```
core-js/proposals/array-filtering
core-js(-pure)/features/array(/virtual)/filter-out
core-js(-pure)/features/typed-array/filter-out
core-js/features/typed-array/filter-out
```
[*Examples*](http://es6.zloirock.ru/#log(%5B1%2C%202%2C%203%2C%204%2C%205%5D.filterOut(it%20%3D%3E%20it%20%25%202))%3B%20%2F%2F%20%3D%3E%20%5B2%2C%204%5D):
```js
[1, 2, 3, 4, 5].filterOut(it => it % 2); // => [2, 4]
````
##### [Array deduplication](https://github.com/tc39/proposal-array-unique)[⬆](#index)
Module [`esnext.array.unique-by`](https://github.com/zloirock/core-js/blob/v3.8.3/packages/core-js/modules/esnext.array.unique-by.js)
Modules [`esnext.array.unique-by`](https://github.com/zloirock/core-js/blob/v3.8.3/packages/core-js/modules/esnext.array.unique-by.js) and [`esnext.typed-array.unique-by`](https://github.com/zloirock/core-js/blob/v3.8.3/packages/core-js/modules/esnext.typed-array.unique-by.js)
```js
class Array {
uniqueBy(resolver?: (item: any) => any): Array<mixed>;
}
class %TypedArray% {
uniqueBy(resolver?: (item: any) => any): %TypedArray%;;
}
```
[*CommonJS entry points:*](#commonjs-api)
```
core-js/proposals/array-unique
core-js(-pure)/features/array(/virtual)/unique-by
core-js/features/typed-array/unique-by
```
[*Examples*](http://es6.zloirock.ru/#log(%5B1%2C%202%2C%203%2C%202%2C%201%5D.uniqueBy())%3B%20%20%2F%2F%20%5B1%2C%202%2C%203%5D%0A%0Aconst%20data%20%3D%20%5B%0A%20%20%7B%20id%3A%201%2C%20uid%3A%2010000%20%7D%2C%0A%20%20%7B%20id%3A%202%2C%20uid%3A%2010000%20%7D%2C%0A%20%20%7B%20id%3A%203%2C%20uid%3A%2010001%20%7D%0A%5D%3B%0A%0Alog(data.uniqueBy('uid'))%3B%20%2F%2F%20%3D%3E%20%5B%7B%20id%3A%201%2C%20uid%3A%2010000%20%7D%2C%20%7B%20id%3A%203%2C%20uid%3A%2010001%20%7D%5D%0A%0Alog(data.uniqueBy((%7B%20id%2C%20uid%20%7D)%20%3D%3E%20%60%24%7Bid%7D-%24%7Buid%7D%60))%3B%20%2F%2F%20%3D%3E%20%5B%7B%20id%3A%201%2C%20uid%3A%2010000%20%7D%2C%20%7B%20id%3A%202%2C%20uid%3A%2010000%20%7D%2C%20%7B%20id%3A%203%2C%20uid%3A%2010001%20%7D%5D):
```js
Expand All @@ -2456,17 +2444,7 @@ class Array {
findLastIndex(callbackfn: (value: any, index: number, target: any) => boolean, thisArg?: any): uint;
}
class [
Int8Array,
Uint8Array,
Uint8ClampedArray,
Int16Array,
Uint16Array,
Int32Array,
Uint32Array,
Float32Array,
Float64Array,
] {
class %TypedArray% {
findLast(callbackfn: (value: any, index: number, target: %TypedArray%) => boolean, thisArg?: any): any;
findLastIndex(callbackfn: (value: any, index: number, target: %TypedArray%) => boolean, thisArg?: any): uint;
}
Expand All @@ -2476,8 +2454,8 @@ class [
core-js/proposals/array-find-from-last
core-js(-pure)/features(/virtual)/array/find-last
core-js(-pure)/features(/virtual)/array/find-last-index
core-js(-pure)/features/typed-array/find-last
core-js(-pure)/features/typed-array/find-last-index
core-js/features/typed-array/find-last
core-js/features/typed-array/find-last-index
```
[*Examples*](http://es6.zloirock.ru/#log(%5B1%2C%202%2C%203%2C%204%5D.findLast(it%20%3D%3E%20it%20%25%202))%3B%20%20%20%20%20%20%2F%2F%20%3D%3E%203%0Alog(%5B1%2C%202%2C%203%2C%204%5D.findLastIndex(it%20%3D%3E%20it%20%25%202))%3B%20%2F%2F%20%3D%3E%202):
```js
Expand Down
2 changes: 2 additions & 0 deletions packages/core-js-compat/src/data.js
Original file line number Diff line number Diff line change
Expand Up @@ -1506,6 +1506,8 @@ const data = {
},
'esnext.typed-array.find-last-index': {
},
'esnext.typed-array.unique-by': {
},
'esnext.weak-map.delete-all': {
},
'esnext.weak-map.from': {
Expand Down
1 change: 1 addition & 0 deletions packages/core-js-compat/src/modules-by-versions.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,5 +78,6 @@ module.exports = {
'esnext.array.find-last-index',
'esnext.typed-array.find-last',
'esnext.typed-array.find-last-index',
'esnext.typed-array.unique-by',
],
};
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// empty
1 change: 1 addition & 0 deletions packages/core-js/features/array/virtual/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
var parent = require('../../../es/array/virtual');
require('../../../modules/es.map');
require('../../../modules/esnext.array.at');
require('../../../modules/esnext.array.filter-out');
require('../../../modules/esnext.array.find-last');
Expand Down
2 changes: 2 additions & 0 deletions packages/core-js/features/typed-array/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
var parent = require('../../es/typed-array');
require('../../modules/es.map');
require('../../modules/esnext.typed-array.at');
require('../../modules/esnext.typed-array.filter-out');
require('../../modules/esnext.typed-array.find-last');
require('../../modules/esnext.typed-array.find-last-index');
require('../../modules/esnext.typed-array.unique-by');

module.exports = parent;
2 changes: 2 additions & 0 deletions packages/core-js/features/typed-array/unique-by.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
require('../../modules/es.map');
require('../../modules/esnext.typed-array.unique-by');
32 changes: 32 additions & 0 deletions packages/core-js/internals/array-unique-by.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
'use strict';
var toLength = require('../internals/to-length');
var toObject = require('../internals/to-object');
var getBuiltIn = require('../internals/get-built-in');
var arraySpeciesCreate = require('../internals/array-species-create');

var push = [].push;

// `Array.prototype.uniqueBy` method
// https://github.com/tc39/proposal-array-unique
module.exports = function uniqueBy(resolver) {
var that = toObject(this);
var length = toLength(that.length);
var result = arraySpeciesCreate(that, 0);
var Map = getBuiltIn('Map');
var map = new Map();
var resolverFunction, index, item, key;
if (typeof resolver == 'function') resolverFunction = resolver;
else if (resolver == null) resolverFunction = function (value) {
return value;
};
else throw new TypeError('Incorrect resolver!');
for (index = 0; index < length; index++) {
item = that[index];
key = resolverFunction(item);
if (!map.has(key)) map.set(key, item);
}
map.forEach(function (value) {
push.call(result, value);
});
return result;
};
11 changes: 11 additions & 0 deletions packages/core-js/internals/typed-array-from-species-and-list.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
var aTypedArrayConstructor = require('../internals/array-buffer-view-core').aTypedArrayConstructor;
var speciesConstructor = require('../internals/species-constructor');

module.exports = function (instance, list) {
var C = speciesConstructor(instance, instance.constructor);
var index = 0;
var length = list.length;
var result = new (aTypedArrayConstructor(C))(length);
while (length > index) result[index] = list[index++];
return result;
};
10 changes: 2 additions & 8 deletions packages/core-js/modules/es.typed-array.filter.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
'use strict';
var ArrayBufferViewCore = require('../internals/array-buffer-view-core');
var $filter = require('../internals/array-iteration').filter;
var speciesConstructor = require('../internals/species-constructor');
var fromSpeciesAndList = require('../internals/typed-array-from-species-and-list');

var aTypedArray = ArrayBufferViewCore.aTypedArray;
var aTypedArrayConstructor = ArrayBufferViewCore.aTypedArrayConstructor;
var exportTypedArrayMethod = ArrayBufferViewCore.exportTypedArrayMethod;

// `%TypedArray%.prototype.filter` method
// https://tc39.es/ecma262/#sec-%typedarray%.prototype.filter
exportTypedArrayMethod('filter', function filter(callbackfn /* , thisArg */) {
var list = $filter(aTypedArray(this), callbackfn, arguments.length > 1 ? arguments[1] : undefined);
var C = speciesConstructor(this, this.constructor);
var index = 0;
var length = list.length;
var result = new (aTypedArrayConstructor(C))(length);
while (length > index) result[index] = list[index++];
return result;
return fromSpeciesAndList(this, list);
});
30 changes: 2 additions & 28 deletions packages/core-js/modules/esnext.array.unique-by.js
Original file line number Diff line number Diff line change
@@ -1,38 +1,12 @@
'use strict';
var $ = require('../internals/export');
var toLength = require('../internals/to-length');
var toObject = require('../internals/to-object');
var getBuiltIn = require('../internals/get-built-in');
var arraySpeciesCreate = require('../internals/array-species-create');
var addToUnscopables = require('../internals/add-to-unscopables');

var push = [].push;
var uniqueBy = require('../internals/array-unique-by');

// `Array.prototype.uniqueBy` method
// https://github.com/tc39/proposal-array-unique
$({ target: 'Array', proto: true }, {
uniqueBy: function uniqueBy(resolver) {
var that = toObject(this);
var length = toLength(that.length);
var result = arraySpeciesCreate(that, 0);
var Map = getBuiltIn('Map');
var map = new Map();
var resolverFunction, index, item, key;
if (typeof resolver == 'function') resolverFunction = resolver;
else if (resolver == null) resolverFunction = function (value) {
return value;
};
else throw new TypeError('Incorrect resolver!');
for (index = 0; index < length; index++) {
item = that[index];
key = resolverFunction(item);
if (!map.has(key)) map.set(key, item);
}
map.forEach(function (value) {
push.call(result, value);
});
return result;
}
uniqueBy: uniqueBy
});

addToUnscopables('uniqueBy');
10 changes: 2 additions & 8 deletions packages/core-js/modules/esnext.typed-array.filter-out.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
'use strict';
var ArrayBufferViewCore = require('../internals/array-buffer-view-core');
var $filterOut = require('../internals/array-iteration').filterOut;
var speciesConstructor = require('../internals/species-constructor');
var fromSpeciesAndList = require('../internals/typed-array-from-species-and-list');

var aTypedArray = ArrayBufferViewCore.aTypedArray;
var aTypedArrayConstructor = ArrayBufferViewCore.aTypedArrayConstructor;
var exportTypedArrayMethod = ArrayBufferViewCore.exportTypedArrayMethod;

// `%TypedArray%.prototype.filterOut` method
// https://github.com/tc39/proposal-array-filtering
exportTypedArrayMethod('filterOut', function filterOut(callbackfn /* , thisArg */) {
var list = $filterOut(aTypedArray(this), callbackfn, arguments.length > 1 ? arguments[1] : undefined);
var C = speciesConstructor(this, this.constructor);
var index = 0;
var length = list.length;
var result = new (aTypedArrayConstructor(C))(length);
while (length > index) result[index] = list[index++];
return result;
return fromSpeciesAndList(this, list);
});
13 changes: 13 additions & 0 deletions packages/core-js/modules/esnext.typed-array.unique-by.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
'use strict';
var ArrayBufferViewCore = require('../internals/array-buffer-view-core');
var arrayUniqueBy = require('../internals/array-unique-by');
var fromSpeciesAndList = require('../internals/typed-array-from-species-and-list');

var aTypedArray = ArrayBufferViewCore.aTypedArray;
var exportTypedArrayMethod = ArrayBufferViewCore.exportTypedArrayMethod;

// `%TypedArray%.prototype.uniqueBy` method
// https://github.com/tc39/proposal-array-unique
exportTypedArrayMethod('uniqueBy', function uniqueBy(resolver) {
return fromSpeciesAndList(this, arrayUniqueBy.call(aTypedArray(this), resolver));
});
1 change: 1 addition & 0 deletions packages/core-js/proposals/array-unique.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// https://github.com/tc39/proposal-array-unique
require('../modules/es.map');
require('../modules/esnext.array.unique-by');
require('../modules/esnext.typed-array.unique-by');
1 change: 1 addition & 0 deletions tests/commonjs.js
Original file line number Diff line number Diff line change
Expand Up @@ -1707,6 +1707,7 @@ load('features/typed-array/sort');
load('features/typed-array/subarray');
load('features/typed-array/to-locale-string');
load('features/typed-array/to-string');
load('features/typed-array/unique-by');
load('features/typed-array/values');
ok(typeof load('features/typed-array').Uint32Array === 'function');
ok(typeof load('es/string/match') === 'function');
Expand Down
24 changes: 24 additions & 0 deletions tests/tests/esnext.typed-array.unique-by.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { DESCRIPTORS, GLOBAL, TYPED_ARRAYS } from '../helpers/constants';

if (DESCRIPTORS) QUnit.test('%TypedArrayPrototype%.uniqueBy', assert => {
// we can't implement %TypedArrayPrototype% in all engines, so run all tests for each typed array constructor
for (const name in TYPED_ARRAYS) {
const TypedArray = GLOBAL[name];
const { uniqueBy } = TypedArray.prototype;
assert.isFunction(uniqueBy, `${ name }::uniqueBy is function`);
assert.arity(uniqueBy, 1, `${ name }::uniqueBy arity is 1`);
assert.name(uniqueBy, 'uniqueBy', `${ name }::uniqueBy name is 'uniqueBy'`);
assert.looksNative(uniqueBy, `${ name }::uniqueBy looks native`);
const array = new TypedArray([1, 2, 3, 2, 1]);
assert.ok(array.uniqueBy() !== array);
assert.deepEqual(array.uniqueBy(), new TypedArray([1, 2, 3]));
let values = '';
new TypedArray([1, 2, 3]).uniqueBy(value => {
values += value;
});
assert.same(values, '123');
assert.throws(() => uniqueBy.call(null, () => { /* empty */ }), TypeError);
assert.throws(() => uniqueBy.call(undefined, () => { /* empty */ }), TypeError);
assert.throws(() => uniqueBy.call([0], () => { /* empty */ }), "isn't generic");
}
});
1 change: 1 addition & 0 deletions tests/tests/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ import './esnext.typed-array.at';
import './esnext.typed-array.filter-out';
import './esnext.typed-array.find-last';
import './esnext.typed-array.find-last-index';
import './esnext.typed-array.unique-by';
import './esnext.weak-map.delete-all';
import './esnext.weak-map.from';
import './esnext.weak-map.of';
Expand Down

0 comments on commit b369faf

Please sign in to comment.