New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add array grouping proposal #959
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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
1 change: 1 addition & 0 deletions
1
packages/core-js-pure/override/modules/esnext.typed-array.group-by.js
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 @@ | ||
// empty |
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,4 @@ | ||
require('../../modules/esnext.array.group-by'); | ||
var entryUnbind = require('../../internals/entry-unbind'); | ||
|
||
module.exports = entryUnbind('Array', 'groupBy'); |
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,4 @@ | ||
require('../../../modules/esnext.array.group-by'); | ||
var entryVirtual = require('../../../internals/entry-virtual'); | ||
|
||
module.exports = entryVirtual('Array').groupBy; |
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,8 @@ | ||
var groupBy = require('../array/virtual/group-by'); | ||
|
||
var ArrayPrototype = Array.prototype; | ||
|
||
module.exports = function (it) { | ||
var own = it.groupBy; | ||
return it === ArrayPrototype || (it instanceof Array && own === ArrayPrototype.groupBy) ? groupBy : own; | ||
}; |
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 @@ | ||
require('../../modules/esnext.typed-array.group-by'); |
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,33 @@ | ||
var bind = require('../internals/function-bind-context'); | ||
var IndexedObject = require('../internals/indexed-object'); | ||
var toObject = require('../internals/to-object'); | ||
var toLength = require('../internals/to-length'); | ||
var toPropertyKey = require('../internals/to-property-key'); | ||
var objectCreate = require('../internals/object-create'); | ||
var arrayFromConstructorAndList = require('../internals/array-from-constructor-and-list'); | ||
|
||
var push = [].push; | ||
|
||
module.exports = function ($this, callbackfn, that, specificConstructor) { | ||
var O = toObject($this); | ||
var self = IndexedObject(O); | ||
var boundFunction = bind(callbackfn, that, 3); | ||
var target = objectCreate(null); | ||
var length = toLength(self.length); | ||
var index = 0; | ||
var Constructor, key, value; | ||
for (;length > index; index++) { | ||
value = self[index]; | ||
key = toPropertyKey(boundFunction(value, index, O)); | ||
// in some IE10 builds, `hasOwnProperty` returns incorrect result on integer keys | ||
// but since it's a `null` prototype object, we can safely use `in` | ||
if (key in target) push.call(target[key], value); | ||
else target[key] = [value]; | ||
} | ||
if (specificConstructor) { | ||
Constructor = specificConstructor(O); | ||
if (Constructor !== Array) { | ||
for (key in target) target[key] = arrayFromConstructorAndList(Constructor, target[key]); | ||
} | ||
} return target; | ||
}; |
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,16 @@ | ||
'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); | ||
} | ||
}); | ||
|
||
addToUnscopables('groupBy'); |
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,14 @@ | ||
'use strict'; | ||
var ArrayBufferViewCore = require('../internals/array-buffer-view-core'); | ||
var $groupBy = require('../internals/array-group-by'); | ||
var typedArraySpeciesConstructor = require('../internals/typed-array-species-constructor'); | ||
|
||
var aTypedArray = ArrayBufferViewCore.aTypedArray; | ||
var exportTypedArrayMethod = ArrayBufferViewCore.exportTypedArrayMethod; | ||
|
||
// `%TypedArray%.prototype.groupBy` method | ||
// https://github.com/tc39/proposal-array-grouping | ||
exportTypedArrayMethod('groupBy', function groupBy(callbackfn /* , thisArg */) { | ||
var thisArg = arguments.length > 1 ? arguments[1] : undefined; | ||
return $groupBy(aTypedArray(this), callbackfn, thisArg, typedArraySpeciesConstructor); | ||
}); |
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 @@ | ||
// https://github.com/tc39/proposal-array-grouping | ||
require('../modules/esnext.array.group-by'); | ||
require('../modules/esnext.typed-array.group-by'); |
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,36 @@ | ||
import { STRICT } from '../helpers/constants'; | ||
|
||
import Symbol from 'core-js-pure/features/symbol'; | ||
import groupBy from 'core-js-pure/features/array/group-by'; | ||
import getPrototypeOf from 'core-js-pure/features/object/get-prototype-of'; | ||
|
||
QUnit.test('Array#groupBy', assert => { | ||
assert.isFunction(groupBy); | ||
let array = [1]; | ||
const context = {}; | ||
groupBy(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.same(getPrototypeOf(groupBy([], it => it)), null, 'null proto'); | ||
assert.deepEqual(groupBy([1, 2, 3], it => it % 2), { 1: [1, 3], 0: [2] }, '#1'); | ||
assert.deepEqual( | ||
groupBy([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(groupBy(Array(3), it => it), { undefined: [undefined, undefined, undefined] }, '#3'); | ||
if (STRICT) { | ||
assert.throws(() => groupBy(null, () => { /* empty */ }), TypeError); | ||
assert.throws(() => groupBy(undefined, () => { /* empty */ }), TypeError); | ||
} | ||
array = [1]; | ||
// eslint-disable-next-line object-shorthand -- constructor | ||
array.constructor = { [Symbol.species]: function () { | ||
return { foo: 1 }; | ||
} }; | ||
assert.same(groupBy(array, Boolean).true.foo, 1, '@@species'); | ||
}); |
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,39 @@ | ||
import { STRICT } from '../helpers/constants'; | ||
|
||
const { getPrototypeOf } = Object; | ||
|
||
QUnit.test('Array#groupBy', assert => { | ||
const { groupBy } = Array.prototype; | ||
assert.isFunction(groupBy); | ||
assert.arity(groupBy, 1); | ||
assert.name(groupBy, 'groupBy'); | ||
assert.looksNative(groupBy); | ||
assert.nonEnumerable(Array.prototype, 'groupBy'); | ||
let array = [1]; | ||
const context = {}; | ||
array.groupBy(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.same(getPrototypeOf([].groupBy(it => it)), null, 'null proto'); | ||
assert.deepEqual([1, 2, 3].groupBy(it => it % 2), { 1: [1, 3], 0: [2] }, '#1'); | ||
assert.deepEqual( | ||
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12].groupBy(it => `i${ it % 5 }`), | ||
{ i1: [1, 6, 11], i2: [2, 7, 12], i3: [3, 8], i4: [4, 9], i0: [5, 10] }, | ||
'#2', | ||
); | ||
assert.deepEqual(Array(3).groupBy(it => it), { undefined: [undefined, undefined, undefined] }, '#3'); | ||
if (STRICT) { | ||
assert.throws(() => groupBy.call(null, () => { /* empty */ }), TypeError); | ||
assert.throws(() => groupBy.call(undefined, () => { /* empty */ }), TypeError); | ||
} | ||
array = [1]; | ||
// eslint-disable-next-line object-shorthand -- constructor | ||
array.constructor = { [Symbol.species]: function () { | ||
return { foo: 1 }; | ||
} }; | ||
assert.same(array.groupBy(Boolean).true.foo, 1, '@@species'); | ||
}); |
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,42 @@ | ||
import { DESCRIPTORS, GLOBAL, TYPED_ARRAYS } from '../helpers/constants'; | ||
|
||
const { getPrototypeOf } = Object; | ||
|
||
if (DESCRIPTORS) QUnit.test('%TypedArrayPrototype%.groupBy', 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 { groupBy } = TypedArray.prototype; | ||
assert.isFunction(groupBy, `${ name }::groupBy is function`); | ||
assert.arity(groupBy, 1, `${ name }::groupBy arity is 1`); | ||
assert.name(groupBy, 'groupBy', `${ name }::groupBy name is 'groupBy'`); | ||
assert.looksNative(groupBy, `${ name }::groupBy looks native`); | ||
const array = new TypedArray([1]); | ||
const context = {}; | ||
array.groupBy(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.same(getPrototypeOf(new TypedArray([1]).groupBy(it => it)), null, 'null proto'); | ||
assert.ok(new TypedArray([1]).groupBy(it => it)[1] instanceof TypedArray, 'instance'); | ||
assert.deepEqual( | ||
new TypedArray([1, 2, 3]).groupBy(it => it % 2), | ||
{ 1: new TypedArray([1, 3]), 0: new TypedArray([2]) }, | ||
'#1', | ||
); | ||
assert.deepEqual(new TypedArray([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]).groupBy(it => `i${ it % 5 }`), { | ||
i1: new TypedArray([1, 6, 11]), | ||
i2: new TypedArray([2, 7, 12]), | ||
i3: new TypedArray([3, 8]), | ||
i4: new TypedArray([4, 9]), | ||
i0: new TypedArray([5, 10]), | ||
}, '#2'); | ||
|
||
assert.throws(() => groupBy.call([0], () => { /* empty */ }), "isn't generic"); | ||
} | ||
}); | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: I switched a List type in the current spec, but I don't know how you implement list (it may just be a normal array?) But I think this exposes set operations in an incorrect order?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lists are unobservable, so it's optimized for direct adding plain arrays to the
null
prototype object. If it's a custom array constructor or a typed array, they are created on a second loop pass and all observable operations evaluated in the correct order. The only observable difference with the current spec draft is an optimization of getting@@species
constructor.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, it's possible to define setters on
Array.prototype
orObject.prototype
and observe it, but I think that it's an acceptable limitation. This is a limitation of all polyfills of features that useList
that I know. It's possible to use arrays withnull
prototype or objects withnull
prototype, but I don't think that it's worth it.