Skip to content

Commit

Permalink
add compositeKey method from richer keys proposal
Browse files Browse the repository at this point in the history
  • Loading branch information
zloirock committed May 5, 2018
1 parent 15c790f commit 2777bd7
Show file tree
Hide file tree
Showing 12 changed files with 176 additions and 0 deletions.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,7 @@ module.exports = {
},
globals: {
asap: true,
compositeKey: true,
Observable: true,
},
},
Expand Down
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1691,6 +1691,36 @@ Set.of(1, 2, 3, 2, 1); // => Set {1, 2, 3}
Map.from([[1, 2], [3, 4]], ([key, value]) => [key ** 2, value ** 2]); // => Map {1: 4, 9: 16}
```
* `compositeKey` method from richer keys [proposal](https://github.com/bmeck/proposal-richer-keys/tree/master/compositeKey) - module [`esnext.composite-key`](https://github.com/zloirock/core-js/blob/v3/packages/core-js/modules/esnext.composite-key.js)
```js
function compositeKey(...args: Array<mixed>): object;
```
[*CommonJS entry points:*](#commonjs)
```js
core-js(-pure)/features/composite-key
```
[*Examples*](https://goo.gl/2oPAH7):
```js
// returns a plain frozen object without a prototype
const key = compositeKey({});
console.log(typeof key); // => 'object'
console.log({}.toString.call(key)); // => '[object Object]'
console.log(Object.getPrototypeOf(key)); // => null
console.log(Object.isFrozen(key)); // => true
const a = ['a'];
const b = ['b'];
const c = ['c'];
console.log(compositeKey(a) === compositeKey(a)); // => true
console.log(compositeKey(a) !== compositeKey(['a'])); // => true
console.log(compositeKey(a, 1) === compositeKey(a, 1)); // => true
console.log(compositeKey(a, b) !== compositeKey(b, a)); // => true
console.log(compositeKey(a, b, c) === compositeKey(a, b, c)); // => true
console.log(compositeKey(1, a) === compositeKey(1, a)); // => true
console.log(compositeKey(1, a, 2, b) === compositeKey(1, a, 2, b)); // => true
console.log(compositeKey(a, a) === compositeKey(a, a)); // => true
```
* `Observable` [proposal](https://github.com/zenparsing/es-observable) - modules [`esnext.observable`](https://github.com/zloirock/core-js/blob/v3/packages/core-js/modules/esnext.observable.js) and [`esnext.symbol.observable`](https://github.com/zloirock/core-js/blob/v3/packages/core-js/modules/esnext.symbol.observable.js)
```js
class Observable {
Expand Down
1 change: 1 addition & 0 deletions packages/core-js-builder/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ module.exports = {
'esnext.array.last-index',
'esnext.array.last-item',
'esnext.asap',
'esnext.composite-key',
'esnext.global',
'esnext.map.from',
'esnext.map.group-by',
Expand Down
3 changes: 3 additions & 0 deletions packages/core-js/features/composite-key.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
require('../modules/esnext.composite-key');

module.exports = require('../internals/path').compositeKey;
1 change: 1 addition & 0 deletions packages/core-js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ require('./modules/esnext.array.flat-map');
require('./modules/esnext.array.last-index');
require('./modules/esnext.array.last-item');
require('./modules/esnext.asap');
require('./modules/esnext.composite-key');
require('./modules/esnext.global');
require('./modules/esnext.map.from');
require('./modules/esnext.map.group-by');
Expand Down
44 changes: 44 additions & 0 deletions packages/core-js/modules/esnext.composite-key.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
var Map = require('../modules/es.map');
var WeakMap = require('../modules/es.weak-map');
var create = require('../internals/object-create');
var isObject = require('../internals/is-object');
var $Object = require('../internals/path').Object;
var freeze = $Object && $Object.freeze;

var Node = function () {
this.value = null;
this.primitives = null;
this.objectsByIndex = create(null);
};

Node.prototype.get = function () {
return this.value || (this.value = freeze ? freeze(create(null)) : create(null));
};

Node.prototype.next = function (i, it, IS_OBJECT) {
var store = IS_OBJECT
? this.objectsByIndex[i] || (this.objectsByIndex[i] = new WeakMap())
: this.primitives || (this.primitives = new Map());
var entry = store.get(it);
if (!entry) store.set(it, entry = new Node());
return entry;
};

var root = new Node();

require('../internals/export')({ global: true }, {
compositeKey: function compositeKey() {
var active = root;
var length = arguments.length;
var i, it;
// for prevent leaking, start from objects
for (i = 0; i < length; i++) {
if (isObject(it = arguments[i])) active = active.next(i, it, true);
}
if (active === root) throw TypeError('Composite keys must contain a non-primitive component');
for (i = 0; i < length; i++) {
if (!isObject(it = arguments[i])) active = active.next(i, it, false);
}
return active.get();
}
});
1 change: 1 addition & 0 deletions packages/core-js/stage/1.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,6 @@ require('../modules/esnext.weak-map.from');
require('../modules/esnext.weak-map.of');
require('../modules/esnext.weak-set.from');
require('../modules/esnext.weak-set.of');
require('../modules/esnext.composite-key');

module.exports = require('./2');
1 change: 1 addition & 0 deletions tests/commonjs.js
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ for (const _PATH of ['../packages/core-js-pure', '../packages/core-js']) {
ok(typeof load('features/set-immediate') === 'function');
ok(typeof load('features/clear-immediate') === 'function');
ok(typeof load('features/asap') === 'function');
ok(typeof load('features/composite-key')({}, 1, {}) === 'object');
ok(load('features/is-iterable')([]));
ok(typeof load('features/get-iterator-method')([]) === 'function');
ok('next' in load('features/get-iterator')([]));
Expand Down
46 changes: 46 additions & 0 deletions tests/pure/esnext.composite-key.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/* eslint-disable no-self-compare */
import { FREEZING } from '../helpers/constants';

import compositeKey from 'core-js-pure/features/composite-key';
import { getPrototypeOf, isFrozen } from 'core-js-pure/features/object';

QUnit.test('compositeKey', assert => {
assert.isFunction(compositeKey);
if (compositeKey.name) assert.name(compositeKey, 'compositeKey');

const key = compositeKey({});
assert.same(typeof key, 'object');
assert.same({}.toString.call(key), '[object Object]');
assert.same(getPrototypeOf(key), null);
if (FREEZING) assert.ok(isFrozen(key));

const a = ['a'];
const b = ['b'];
const c = ['c'];

assert.ok(compositeKey(a) === compositeKey(a));
assert.ok(compositeKey(a) !== compositeKey(['a']));
assert.ok(compositeKey(a) !== compositeKey(a, 1));
assert.ok(compositeKey(a) !== compositeKey(a, b));
assert.ok(compositeKey(a, 1) === compositeKey(a, 1));
assert.ok(compositeKey(a, b) === compositeKey(a, b));
assert.ok(compositeKey(a, b) !== compositeKey(b, a));
assert.ok(compositeKey(a, b, c) === compositeKey(a, b, c));
assert.ok(compositeKey(a, b, c) !== compositeKey(c, b, a));
assert.ok(compositeKey(a, b, c) !== compositeKey(a, c, b));
assert.ok(compositeKey(a, b, c, 1) !== compositeKey(a, b, c));
assert.ok(compositeKey(a, b, c, 1) === compositeKey(a, b, c, 1));
assert.ok(compositeKey(1, a) === compositeKey(1, a));
assert.ok(compositeKey(1, a) !== compositeKey(a, 1));
assert.ok(compositeKey(1, a, 2, b) === compositeKey(1, a, 2, b));
assert.ok(compositeKey(1, a, 2, b) !== compositeKey(1, a, b, 2));
assert.ok(compositeKey(1, 2, a, b) === compositeKey(1, 2, a, b));
assert.ok(compositeKey(1, 2, a, b) !== compositeKey(1, a, b, 2));
assert.ok(compositeKey(a, a) === compositeKey(a, a));
assert.ok(compositeKey(a, a) !== compositeKey(a, ['a']));
assert.ok(compositeKey(a, a) !== compositeKey(a, b));

assert.throws(() => compositeKey(), TypeError);
assert.throws(() => compositeKey(1, 2), TypeError);
assert.throws(() => compositeKey('foo', null, true), TypeError);
});
1 change: 1 addition & 0 deletions tests/pure/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ QUnit.module('ESNext');
import './esnext.array.flat-map';
import './esnext.array.flatten';
import './esnext.asap';
import './esnext.composite-key';
import './esnext.global';
import './esnext.math.clamp';
import './esnext.math.deg-per-rad';
Expand Down
46 changes: 46 additions & 0 deletions tests/tests/esnext.composite-key.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/* eslint-disable no-self-compare */
import { FREEZING } from '../helpers/constants';

const { getPrototypeOf, isFrozen } = Object;

QUnit.test('compositeKey', assert => {
assert.isFunction(compositeKey);
assert.name(compositeKey, 'compositeKey');
assert.looksNative(compositeKey);

const key = compositeKey({});
assert.same(typeof key, 'object');
assert.same({}.toString.call(key), '[object Object]');
assert.same(getPrototypeOf(key), null);
if (FREEZING) assert.ok(isFrozen(key));

const a = ['a'];
const b = ['b'];
const c = ['c'];

assert.ok(compositeKey(a) === compositeKey(a));
assert.ok(compositeKey(a) !== compositeKey(['a']));
assert.ok(compositeKey(a) !== compositeKey(a, 1));
assert.ok(compositeKey(a) !== compositeKey(a, b));
assert.ok(compositeKey(a, 1) === compositeKey(a, 1));
assert.ok(compositeKey(a, b) === compositeKey(a, b));
assert.ok(compositeKey(a, b) !== compositeKey(b, a));
assert.ok(compositeKey(a, b, c) === compositeKey(a, b, c));
assert.ok(compositeKey(a, b, c) !== compositeKey(c, b, a));
assert.ok(compositeKey(a, b, c) !== compositeKey(a, c, b));
assert.ok(compositeKey(a, b, c, 1) !== compositeKey(a, b, c));
assert.ok(compositeKey(a, b, c, 1) === compositeKey(a, b, c, 1));
assert.ok(compositeKey(1, a) === compositeKey(1, a));
assert.ok(compositeKey(1, a) !== compositeKey(a, 1));
assert.ok(compositeKey(1, a, 2, b) === compositeKey(1, a, 2, b));
assert.ok(compositeKey(1, a, 2, b) !== compositeKey(1, a, b, 2));
assert.ok(compositeKey(1, 2, a, b) === compositeKey(1, 2, a, b));
assert.ok(compositeKey(1, 2, a, b) !== compositeKey(1, a, b, 2));
assert.ok(compositeKey(a, a) === compositeKey(a, a));
assert.ok(compositeKey(a, a) !== compositeKey(a, ['a']));
assert.ok(compositeKey(a, a) !== compositeKey(a, b));

assert.throws(() => compositeKey(), TypeError);
assert.throws(() => compositeKey(1, 2), TypeError);
assert.throws(() => compositeKey('foo', null, true), TypeError);
});
1 change: 1 addition & 0 deletions tests/tests/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ import './esnext.array.last-index';
import './esnext.array.flat-map';
import './esnext.array.flatten';
import './esnext.asap';
import './esnext.composite-key';
import './esnext.global';
import './esnext.map.from';
import './esnext.map.of';
Expand Down

0 comments on commit 2777bd7

Please sign in to comment.