Skip to content

Commit

Permalink
Merge pull request #1001 from zloirock/tc39-october-2021
Browse files Browse the repository at this point in the history
  • Loading branch information
zloirock authored Dec 9, 2021
2 parents 4d91951 + bcda388 commit 65c36d8
Show file tree
Hide file tree
Showing 24 changed files with 158 additions and 26 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
## Changelog
##### Unreleased
- [`Array` grouping proposal](https://github.com/tc39/proposal-array-grouping):
- Moved to the stage 2
- Added `Array.prototype.groupByMap` method
- Removed `@@species` support
- Added [change `Array` by copy stage 2 proposal](https://github.com/tc39/proposal-change-array-by-copy):
- `Array.prototype.toReversed`
- `Array.prototype.toSorted`
Expand Down
24 changes: 9 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ Promise.resolve(32).then(x => console.log(x)); // => 32
- [`Iterator` helpers](#iterator-helpers)
- [New `Set` methods](#new-set-methods)
- [`Map.prototype.emplace`](#mapprototypeemplace)
- [`Array` grouping](#array-grouping)
- [Change `Array` by copy](#change-array-by-copy)
- [`Array.isTemplateObject`](#arrayistemplateobject)
- [`Symbol.{ asyncDispose, dispose }` for `using` statement](#symbol-asyncdispose-dispose--for-using-statement)
Expand All @@ -112,7 +113,6 @@ Promise.resolve(32).then(x => console.log(x)); // => 32
- [`compositeKey` and `compositeSymbol`](#compositekey-and-compositesymbol)
- [`Array.fromAsync`](#arrayfromasync)
- [`Array` filtering](#array-filtering)
- [`Array` grouping](#array-grouping)
- [`Array` deduplication](#array-deduplication)
- [Getting last item from `Array`](#getting-last-item-from-array)
- [`Number.range`](#numberrange)
Expand Down Expand Up @@ -2353,21 +2353,16 @@ console.log(compositeSymbol(1, a, 2, b) === compositeSymbol(1, a, 2, b)); // =>
console.log(compositeSymbol(a, a) === compositeSymbol(a, a)); // => true
```
##### [`Array.fromAsync`](https://github.com/tc39/proposal-array-from-async)[⬆](#index)
Modules [`esnext.array.from-async`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.array.from-async.js) and [`esnext.typed-array.from-async`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.typed-array.from-async.js)
Modules [`esnext.array.from-async`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.array.from-async.js).
```js
class Array {
static fromAsync(asyncItems: AsyncIterable | Iterable | ArrayLike, mapfn?: (value: any, index: number) => any, thisArg?: any): Array;
}
class %TypedArray% {
static fromAsync(asyncItems: AsyncIterable | Iterable | ArrayLike, mapfn?: (value: number, index: number, target) => number, thisArg?: any): %TypedArray%;
}
```
[*CommonJS entry points:*](#commonjs-api)
```js
core-js/proposals/array-from-async
core-js(-pure)/features/array/from-async
core-js/features/typed-array/from-async
```
[*Example*](https://goo.gl/Jt7SsD):
```js
Expand Down Expand Up @@ -2395,26 +2390,25 @@ core-js/features/typed-array/filter-reject
[1, 2, 3, 4, 5].filterReject(it => it % 2); // => [2, 4]
````
##### [`Array` grouping](#https://github.com/tc39/proposal-array-grouping)[⬆](#index)
Modules [`esnext.array.group-by`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.array.group-by.js) and [`esnext.typed-array.group-by`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.typed-array.group-by.js).
Modules [`esnext.array.group-by`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.array.group-by.js), [`esnext.array.group-by-map`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.array.group-by-map.js).
```js
class Array {
groupBy(callbackfn: (value: any, index: number, target: any) => key, thisArg?: any): { [key]: Array<mixed> };
groupByMap(callbackfn: (value: any, index: number, target: any) => key, thisArg?: any): Map<key, Array<mixed>>;
}

class %TypedArray% {
groupBy(callbackfn: (value: number, index: number, target: %TypedArray%) => key, thisArg?: any): { [key]: %TypedArray% };
}
```
[*CommonJS entry points:*](#commonjs-api)
```
core-js/proposals/array-grouping
core-js(-pure)/features/array(/virtual)/group-by
core-js/features/typed-array/group-by
core-js(-pure)/features/array(/virtual)/group-by-map
```
[*Examples*](t.ly/VggI):
[*Examples*](t.ly/xEqc):
```js
[1, 2, 3, 4, 5].groupBy(it => it % 2); // => { 1: [1, 3, 5], 0: [2, 4] }
const map = [1, 2, 3, 4, 5].groupByMap(it => it % 2);
map.get(1); // => [1, 3, 5]
map.get(0); // => [2, 4]
````
##### [Array deduplication](https://github.com/tc39/proposal-array-unique)[⬆](#index)
Modules [`esnext.array.unique-by`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.array.unique-by.js) and [`esnext.typed-array.unique-by`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.typed-array.unique-by.js)
Expand Down Expand Up @@ -3086,4 +3080,4 @@ console.log(getIteratorMethod({})); // undefined
- ES `Proxy` can't be polyfilled, you can try to use [`proxy-polyfill`](https://github.com/GoogleChrome/proxy-polyfill) which provides a very little subset of features.
- ES `String#normalize` is not a very useful feature, but this polyfill will be very large. If you need it, you can use [unorm](https://github.com/walling/unorm/).
- ECMA-402 `Intl` is missed because of the size. You can use [those polyfills](https://formatjs.io/docs/polyfills).
- `window.fetch` is not a cross-platform feature, in some environments, it makes no sense. For this reason, I don't think it should be in `core-js`. Looking at a large number of requests it *might be* added in the future. Now you can use, for example, [this polyfill](https://github.com/github/fetch).
- `window.fetch` is not a cross-platform feature, in some environments, it makes no sense. For this reason, I don't think it should be in `core-js`. Looking at a large number of requests it *might be* added in the future. Now you can use, for example, [this polyfill](https://github.com/github/fetch).
4 changes: 4 additions & 0 deletions packages/core-js-compat/src/data.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -1451,6 +1451,8 @@ export const data = {
},
'esnext.array.group-by': {
},
'esnext.array.group-by-map': {
},
'esnext.array.is-template-object': {
},
// TODO: Remove from `core-js@4`
Expand Down Expand Up @@ -1728,6 +1730,7 @@ export const data = {
// TODO: Remove from `core-js@4`
'esnext.symbol.replace-all': {
},
// TODO: Remove from `core-js@4`
'esnext.typed-array.from-async': {
},
// TODO: Remove from `core-js@4`
Expand All @@ -1745,6 +1748,7 @@ export const data = {
chrome: '97',
safari: '15.4',
},
// TODO: Remove from `core-js@4`
'esnext.typed-array.group-by': {
},
'esnext.typed-array.to-reversed': {
Expand Down
1 change: 1 addition & 0 deletions packages/core-js-compat/src/modules-by-versions.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ export default {
'esnext.typed-array.from-async',
],
'3.20': [
'esnext.array.group-by-map',
'esnext.array.to-reversed',
'esnext.array.to-sorted',
'esnext.array.to-spliced',
Expand Down
5 changes: 5 additions & 0 deletions packages/core-js/features/array/group-by-map.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
require('../../modules/es.map');
require('../../modules/esnext.array.group-by-map');
var entryUnbind = require('../../internals/entry-unbind');

module.exports = entryUnbind('Array', 'groupByMap');
1 change: 1 addition & 0 deletions packages/core-js/features/array/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ require('../../modules/esnext.array.filter-reject');
require('../../modules/esnext.array.find-last');
require('../../modules/esnext.array.find-last-index');
require('../../modules/esnext.array.group-by');
require('../../modules/esnext.array.group-by-map');
require('../../modules/esnext.array.is-template-object');
require('../../modules/esnext.array.last-item');
require('../../modules/esnext.array.last-index');
Expand Down
5 changes: 5 additions & 0 deletions packages/core-js/features/array/virtual/group-by-map.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
require('../../../modules/es.map');
require('../../../modules/esnext.array.group-by-map');
var entryVirtual = require('../../../internals/entry-virtual');

module.exports = entryVirtual('Array').groupByMap;
1 change: 1 addition & 0 deletions packages/core-js/features/array/virtual/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ require('../../../modules/esnext.array.filter-reject');
require('../../../modules/esnext.array.find-last');
require('../../../modules/esnext.array.find-last-index');
require('../../../modules/esnext.array.group-by');
require('../../../modules/esnext.array.group-by-map');
require('../../../modules/esnext.array.to-reversed');
require('../../../modules/esnext.array.to-sorted');
require('../../../modules/esnext.array.to-spliced');
Expand Down
1 change: 1 addition & 0 deletions packages/core-js/internals/array-group-by.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ module.exports = function ($this, callbackfn, that, specificConstructor) {
if (key in target) push(target[key], value);
else target[key] = [value];
}
// TODO: Remove this block from `core-js@4`
if (specificConstructor) {
Constructor = specificConstructor(O);
if (Constructor !== Array) {
Expand Down
38 changes: 38 additions & 0 deletions packages/core-js/modules/esnext.array.group-by-map.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
'use strict';
var $ = require('../internals/export');
var getBuiltIn = require('../internals/get-built-in');
var bind = require('../internals/function-bind-context');
var uncurryThis = require('../internals/function-uncurry-this');
var IndexedObject = require('../internals/indexed-object');
var toObject = require('../internals/to-object');
var lengthOfArrayLike = require('../internals/length-of-array-like');
var addToUnscopables = require('../internals/add-to-unscopables');

var Map = getBuiltIn('Map');
var MapPrototype = Map.prototype;
var mapGet = uncurryThis(MapPrototype.get);
var mapHas = uncurryThis(MapPrototype.has);
var mapSet = uncurryThis(MapPrototype.set);
var push = uncurryThis([].push);

// `Array.prototype.groupByMap` method
// https://github.com/tc39/proposal-array-grouping
$({ target: 'Array', proto: true }, {
groupByMap: function groupByMap(callbackfn /* , thisArg */) {
var O = toObject(this);
var self = IndexedObject(O);
var boundFunction = bind(callbackfn, arguments.length > 1 ? arguments[1] : undefined);
var map = new Map();
var length = lengthOfArrayLike(self);
var index = 0;
var key, value;
for (;length > index; index++) {
value = self[index];
key = boundFunction(value, index, O);
if (mapHas(map, key)) push(mapGet(map, key), value);
else mapSet(map, key, [value]);
} return map;
}
});

addToUnscopables('groupByMap');
3 changes: 1 addition & 2 deletions packages/core-js/modules/esnext.array.group-by.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
'use strict';
var $ = require('../internals/export');
var $groupBy = require('../internals/array-group-by');
var arraySpeciesConstructor = require('../internals/array-species-constructor');
var addToUnscopables = require('../internals/add-to-unscopables');

// `Array.prototype.groupBy` method
// https://github.com/tc39/proposal-array-grouping
$({ target: 'Array', proto: true }, {
groupBy: function groupBy(callbackfn /* , thisArg */) {
var thisArg = arguments.length > 1 ? arguments[1] : undefined;
return $groupBy(this, callbackfn, thisArg, arraySpeciesConstructor);
return $groupBy(this, callbackfn, thisArg);
}
});

Expand Down
1 change: 1 addition & 0 deletions packages/core-js/modules/esnext.typed-array.from-async.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
'use strict';
// TODO: Remove from `core-js@4`
var getBuiltIn = require('../internals/get-built-in');
var aConstructor = require('../internals/a-constructor');
var arrayFromAsync = require('../internals/array-from-async');
Expand Down
1 change: 1 addition & 0 deletions packages/core-js/modules/esnext.typed-array.group-by.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
'use strict';
// TODO: Remove from `core-js@4`
var ArrayBufferViewCore = require('../internals/array-buffer-view-core');
var $groupBy = require('../internals/array-group-by');
var typedArraySpeciesConstructor = require('../internals/typed-array-species-constructor');
Expand Down
1 change: 1 addition & 0 deletions packages/core-js/proposals/array-from-async.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// https://github.com/tc39/proposal-array-from-async
require('../modules/esnext.array.from-async');
// TODO: Remove from `core-js@4`
require('../modules/esnext.typed-array.from-async');
2 changes: 2 additions & 0 deletions packages/core-js/proposals/array-grouping.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// https://github.com/tc39/proposal-array-grouping
require('../modules/esnext.array.group-by');
require('../modules/esnext.array.group-by-map');
// TODO: Remove from `core-js@4`
require('../modules/esnext.typed-array.group-by');
1 change: 0 additions & 1 deletion packages/core-js/stage/1.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
require('../proposals/array-filtering');
require('../proposals/array-from-async');
require('../proposals/array-grouping');
require('../proposals/array-last');
require('../proposals/array-unique');
require('../proposals/collection-methods');
Expand Down
1 change: 1 addition & 0 deletions packages/core-js/stage/2.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
require('../proposals/array-grouping');
require('../proposals/array-is-template-object');
require('../proposals/change-array-by-copy');
require('../proposals/decorators');
Expand Down
2 changes: 2 additions & 0 deletions scripts/check-compat-tests.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ const ignore = new Set([
'esnext.string.at',
'esnext.symbol.pattern-match',
'esnext.symbol.replace-all',
'esnext.typed-array.from-async',
'esnext.typed-array.filter-out',
'esnext.typed-array.group-by',
'esnext.weak-map.upsert',
]);

Expand Down
2 changes: 2 additions & 0 deletions tests/commonjs.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,7 @@ for (PATH of ['core-js-pure', 'core-js']) {
ok(load(NS, 'array/find-last')([1, 2, 3], it => it % 2) === 3);
ok(load(NS, 'array/find-last-index')([1, 2, 3], it => it % 2) === 2);
ok(typeof load(NS, 'array/group-by') == 'function');
ok(typeof load(NS, 'array/group-by-map') == 'function');
ok(typeof load(NS, 'array/is-template-object') == 'function');
load(NS, 'array/last-item');
load(NS, 'array/last-index');
Expand All @@ -580,6 +581,7 @@ for (PATH of ['core-js-pure', 'core-js']) {
ok(load(NS, 'array/virtual/find-last').call([1, 2, 3], it => it % 2) === 3);
ok(load(NS, 'array/virtual/find-last-index').call([1, 2, 3], it => it % 2) === 2);
ok(typeof load(NS, 'array/virtual/group-by') == 'function');
ok(typeof load(NS, 'array/virtual/group-by-map') == 'function');
ok(typeof load(NS, 'array/virtual/unique-by') == 'function');
ok(load(NS, 'array/virtual/with').call([1, 2, 3], 1, 4));
ok(load(NS, 'array/virtual/to-reversed').call([1, 2, 3])[0] === 3);
Expand Down
6 changes: 0 additions & 6 deletions tests/compat/tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -1514,9 +1514,6 @@ GLOBAL.tests = {
'esnext.symbol.observable': function () {
return Symbol.observable;
},
'esnext.typed-array.from-async': function () {
return Int8Array.fromAsync;
},
'esnext.typed-array.filter-reject': function () {
return Int8Array.prototype.filterReject;
},
Expand All @@ -1526,9 +1523,6 @@ GLOBAL.tests = {
'esnext.typed-array.find-last-index': function () {
return Int8Array.prototype.findLastIndex;
},
'esnext.typed-array.group-by': function () {
return Int8Array.prototype.groupBy;
},
'esnext.typed-array.to-reversed': function () {
return Int8Array.prototype.toReversed;
},
Expand Down
37 changes: 37 additions & 0 deletions tests/pure/esnext.array.group-by-map.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { STRICT } from '../helpers/constants';

import Map from 'core-js-pure/es/map';
import Symbol from 'core-js-pure/es/symbol';
import from from 'core-js-pure/es/array/from';
import groupByMap from 'core-js-pure/features/array/group-by-map';

QUnit.test('Array#groupByMap', assert => {
assert.isFunction(groupByMap);
let array = [1];
const context = {};
groupByMap(array, function (value, key, that) {
assert.same(arguments.length, 3, 'correct number of callback arguments');
assert.same(value, 1, 'correct value in callback');
assert.same(key, 0, 'correct index in callback');
assert.same(that, array, 'correct link to array in callback');
assert.same(this, context, 'correct callback context');
}, context);
assert.true(groupByMap([], it => it) instanceof Map, 'returns Map');
assert.deepEqual(from(groupByMap([1, 2, 3], it => it % 2)), [[1, [1, 3]], [0, [2]]], '#1');
assert.deepEqual(
from(groupByMap([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], it => `i${ it % 5 }`)),
[['i1', [1, 6, 11]], ['i2', [2, 7, 12]], ['i3', [3, 8]], ['i4', [4, 9]], ['i0', [5, 10]]],
'#2',
);
assert.deepEqual(from(groupByMap(Array(3), it => it)), [[undefined, [undefined, undefined, undefined]]], '#3');
if (STRICT) {
assert.throws(() => groupByMap(null, () => { /* empty */ }), TypeError);
assert.throws(() => groupByMap(undefined, () => { /* empty */ }), TypeError);
}
array = [1];
// eslint-disable-next-line object-shorthand -- constructor
array.constructor = { [Symbol.species]: function () {
return { foo: 1 };
} };
assert.same(groupByMap(array, Boolean).get(true).foo, undefined, 'no @@species');
});
2 changes: 1 addition & 1 deletion tests/pure/esnext.array.group-by.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,5 @@ QUnit.test('Array#groupBy', assert => {
array.constructor = { [Symbol.species]: function () {
return { foo: 1 };
} };
assert.same(groupBy(array, Boolean).true.foo, 1, '@@species');
assert.same(groupBy(array, Boolean).true.foo, undefined, 'no @@species');
});
39 changes: 39 additions & 0 deletions tests/tests/esnext.array.group-by-map.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { STRICT } from '../helpers/constants';

const { from } = Array;

QUnit.test('Array#groupByMap', assert => {
const { groupByMap } = Array.prototype;
assert.isFunction(groupByMap);
assert.arity(groupByMap, 1);
assert.name(groupByMap, 'groupByMap');
assert.looksNative(groupByMap);
assert.nonEnumerable(Array.prototype, 'groupByMap');
let array = [1];
const context = {};
array.groupByMap(function (value, key, that) {
assert.same(arguments.length, 3, 'correct number of callback arguments');
assert.same(value, 1, 'correct value in callback');
assert.same(key, 0, 'correct index in callback');
assert.same(that, array, 'correct link to array in callback');
assert.same(this, context, 'correct callback context');
}, context);
assert.true([].groupByMap(it => it) instanceof Map, 'returns Map');
assert.deepEqual(from([1, 2, 3].groupByMap(it => it % 2)), [[1, [1, 3]], [0, [2]]], '#1');
assert.deepEqual(
from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12].groupByMap(it => `i${ it % 5 }`)),
[['i1', [1, 6, 11]], ['i2', [2, 7, 12]], ['i3', [3, 8]], ['i4', [4, 9]], ['i0', [5, 10]]],
'#2',
);
assert.deepEqual(from(Array(3).groupByMap(it => it)), [[undefined, [undefined, undefined, undefined]]], '#3');
if (STRICT) {
assert.throws(() => groupByMap.call(null, () => { /* empty */ }), TypeError);
assert.throws(() => groupByMap.call(undefined, () => { /* empty */ }), TypeError);
}
array = [1];
// eslint-disable-next-line object-shorthand -- constructor
array.constructor = { [Symbol.species]: function () {
return { foo: 1 };
} };
assert.same(array.groupByMap(Boolean).get(true).foo, undefined, 'no @@species');
});
2 changes: 1 addition & 1 deletion tests/tests/esnext.array.group-by.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,5 @@ QUnit.test('Array#groupBy', assert => {
array.constructor = { [Symbol.species]: function () {
return { foo: 1 };
} };
assert.same(array.groupBy(Boolean).true.foo, 1, '@@species');
assert.same(array.groupBy(Boolean).true.foo, undefined, 'no @@species');
});

0 comments on commit 65c36d8

Please sign in to comment.