Skip to content

Commit

Permalink
Merge pull request #1150 from zloirock/set-methods
Browse files Browse the repository at this point in the history
  • Loading branch information
zloirock committed Dec 11, 2022
2 parents d32deca + 4adbf16 commit 541c979
Show file tree
Hide file tree
Showing 68 changed files with 815 additions and 186 deletions.
18 changes: 18 additions & 0 deletions CHANGELOG.md
Expand Up @@ -35,6 +35,24 @@
- Added `/actual/` entries, unconditional forced replacement disabled for features that survived to Stage 3
- `.from` accept strings, `.flatMap` throws on strings returned from the callback, [proposal-iterator-helpers/244](https://github.com/tc39/proposal-iterator-helpers/pull/244), [proposal-iterator-helpers/250](https://github.com/tc39/proposal-iterator-helpers/pull/250)
- `.from` and `.flatMap` throws on non-object *iterators*, [proposal-iterator-helpers/253](https://github.com/tc39/proposal-iterator-helpers/pull/253)
- [`Set` methods proposal](https://github.com/tc39/proposal-set-methods):
- Methods:
- `Set.prototype.intersection`
- `Set.prototype.union`
- `Set.prototype.difference`
- `Set.prototype.symmetricDifference`
- `Set.prototype.isSubsetOf`
- `Set.prototype.isSupersetOf`
- `Set.prototype.isDisjointFrom`
- Moved to Stage 3, [November 2022 TC39 meeting](https://github.com/babel/proposals/issues/85#issuecomment-1332175557)
- Reimplemented with [new semantics](https://tc39.es/proposal-set-methods/):
- Optimized performance (iteration over lowest set)
- Accepted only `Set`-like objects as an argument, not all iterables
- Accepted only `Set`s as `this`, no `@@species` support, and other minor changes
- Added `/actual/` entries, unconditional forced replacement changed to feature detection
- For avoiding breaking changes:
- New versions of methods are implemented as new modules and available in new entries or entries where old versions of methods were not available before (like `/actual/` namespace)
- In entries where they were available before (like `/full/` namespace), those methods are available with fallbacks to old semantics (in addition to `Set`-like, they accept iterable objects). This behavior will be removed from the next major release
- [Well-Formed Unicode Strings](https://github.com/tc39/proposal-is-usv-string) proposal:
- Methods:
- `String.prototype.isWellFormed`
Expand Down
71 changes: 35 additions & 36 deletions README.md
Expand Up @@ -129,9 +129,9 @@ queueMicrotask(() => console.log('called as microtask'));
- [`Array.fromAsync`](#arrayfromasync)
- [`Array` grouping](#array-grouping)
- [Change `Array` by copy](#change-array-by-copy)
- [New `Set` methods](#new-set-methods)
- [Well-formed unicode strings](#well-formed-unicode-strings)
- [Stage 2 proposals](#stage-2-proposals)
- [New `Set` methods](#new-set-methods)
- [`Map.prototype.emplace`](#mapprototypeemplace)
- [`Array.isTemplateObject`](#arrayistemplateobject)
- [`Symbol.{ asyncDispose, dispose }` for `using` statement](#symbol-asyncdispose-dispose--for-using-statement)
Expand Down Expand Up @@ -2277,6 +2277,40 @@ const correctionNeeded = [1, 1, 3];
correctionNeeded.with(1, 2); // => [1, 2, 3]
correctionNeeded; // => [1, 1, 3]
````
##### [New `Set` methods](https://github.com/tc39/proposal-set-methods)[⬆](#index)
Modules [`esnext.set.difference.v2`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.set.difference.v2.js), [`esnext.set.intersection.v2`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.set.intersection.v2.js), [`esnext.set.is-disjoint-from.v2`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.set.is-disjoint-from.v2.js), [`esnext.set.is-subset-of.v2`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.set.is-subset-of.v2.js), [`esnext.set.is-superset-of.v2`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.set.is-superset-of.v2.js), [`esnext.set.symmetric-difference.v2`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.set.symmetric-difference.v2.js), [`esnext.set.union.v2`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.set.union.v2.js)
```js
class Set {
difference(other: SetLike<mixed>): Set;
intersection(other: SetLike<mixed>): Set;
isDisjointFrom(other: SetLike<mixed>): boolean;
isSubsetOf(other: SetLike<mixed>): boolean;
isSupersetOf(other: SetLike<mixed>): boolean;
symmetricDifference(other: SetLike<mixed>): Set;
union(other: SetLike<mixed>): Set;
}
```
[*CommonJS entry points:*](#commonjs-api)
```js
core-js/proposals/set-methods-v2
core-js(-pure)/actual|full/set/difference
core-js(-pure)/actual|full/set/intersection
core-js(-pure)/actual|full/set/is-disjoint-from
core-js(-pure)/actual|full/set/is-subset-of
core-js(-pure)/actual|full/set/is-superset-of
core-js(-pure)/actual|full/set/symmetric-difference
core-js(-pure)/actual|full/set/union
```
[*Examples*](https://tinyurl.com/2henaoac):
```js
new Set([1, 2, 3]).union(new Set([3, 4, 5])); // => Set {1, 2, 3, 4, 5}
new Set([1, 2, 3]).intersection(new Set([3, 4, 5])); // => Set {3}
new Set([1, 2, 3]).difference(new Set([3, 4, 5])); // => Set {1, 2}
new Set([1, 2, 3]).symmetricDifference(new Set([3, 4, 5])); // => Set {1, 2, 4, 5}
new Set([1, 2, 3]).isDisjointFrom(new Set([4, 5, 6])); // => true
new Set([1, 2, 3]).isSubsetOf(new Set([5, 4, 3, 2, 1])); // => true
new Set([5, 4, 3, 2, 1]).isSupersetOf(new Set([1, 2, 3])); // => true
```
##### [Well-formed unicode strings](https://github.com/tc39/proposal-is-usv-string)[⬆](#index)
Modules [`esnext.string.is-well-formed`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.string.is-well-formed.js) and [`esnext.string.to-well-formed`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.string.to-well-formed.js)
```js
Expand Down Expand Up @@ -2305,41 +2339,6 @@ core-js(-pure)/actual|full/string(/virtual)/to-well-formed
```
core-js(-pure)/stage/2
```
##### [New `Set` methods](https://github.com/tc39/proposal-set-methods)[⬆](#index)
Modules [`esnext.set.difference`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.set.difference.js), [`esnext.set.intersection`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.set.intersection.js), [`esnext.set.is-disjoint-from`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.set.is-disjoint-from.js), [`esnext.set.is-subset-of`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.set.is-subset-of.js), [`esnext.set.is-superset-of`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.set.is-superset-of.js), [`esnext.set.symmetric-difference`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.set.symmetric-difference.js), [`esnext.set.union`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.set.union.js)
```js
class Set {
difference(iterable: SetLike<mixed>): Set;
intersection(iterable: SetLike<mixed>): Set;
isDisjointFrom(iterable: SetLike<mixed>): boolean;
isSubsetOf(iterable: SetLike<mixed>): boolean;
isSupersetOf(iterable: SetLike<mixed>): boolean;
symmetricDifference(iterable: SetLike<mixed>): Set;
union(iterable: SetLike<mixed>): Set;
}
```
[*CommonJS entry points:*](#commonjs-api)
```js
core-js/proposals/set-methods
core-js(-pure)/full/set/difference
core-js(-pure)/full/set/intersection
core-js(-pure)/full/set/is-disjoint-from
core-js(-pure)/full/set/is-subset-of
core-js(-pure)/full/set/is-superset-of
core-js(-pure)/full/set/symmetric-difference
core-js(-pure)/full/set/union
```
[*Examples*](https://tinyurl.com/2henaoac):
```js
new Set([1, 2, 3]).union(new Set([3, 4, 5])); // => Set {1, 2, 3, 4, 5}
new Set([1, 2, 3]).intersection(new Set([3, 4, 5])); // => Set {3}
new Set([1, 2, 3]).difference(new Set([3, 4, 5])); // => Set {1, 2}
new Set([1, 2, 3]).symmetricDifference(new Set([3, 4, 5])); // => Set {1, 2, 4, 5}

new Set([1, 2, 3]).isDisjointFrom(new Set([4, 5, 6])); // => true
new Set([1, 2, 3]).isSubsetOf(new Set([5, 4, 3, 2, 1])); // => true
new Set([5, 4, 3, 2, 1]).isSupersetOf(new Set([1, 2, 3])); // => true
```
##### [`Map.prototype.emplace`](https://github.com/thumbsupep/proposal-upsert)[⬆](#index)
Modules [`esnext.map.emplace`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.map.emplace.js) and [`esnext.weak-map.emplace`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.weak-map.emplace.js)
```js
Expand Down
21 changes: 21 additions & 0 deletions packages/core-js-compat/src/data.mjs
Expand Up @@ -2071,6 +2071,9 @@ export const data = {
},
'esnext.set.delete-all': {
},
'esnext.set.difference.v2': {
},
// TODO: Remove from `core-js@4`
'esnext.set.difference': {
},
'esnext.set.every': {
Expand All @@ -2081,12 +2084,24 @@ export const data = {
},
'esnext.set.from': {
},
'esnext.set.intersection.v2': {
},
// TODO: Remove from `core-js@4`
'esnext.set.intersection': {
},
'esnext.set.is-disjoint-from.v2': {
},
// TODO: Remove from `core-js@4`
'esnext.set.is-disjoint-from': {
},
'esnext.set.is-subset-of.v2': {
},
// TODO: Remove from `core-js@4`
'esnext.set.is-subset-of': {
},
'esnext.set.is-superset-of.v2': {
},
// TODO: Remove from `core-js@4`
'esnext.set.is-superset-of': {
},
'esnext.set.join': {
Expand All @@ -2099,8 +2114,14 @@ export const data = {
},
'esnext.set.some': {
},
'esnext.set.symmetric-difference.v2': {
},
// TODO: Remove from `core-js@4`
'esnext.set.symmetric-difference': {
},
'esnext.set.union.v2': {
},
// TODO: Remove from `core-js@4`
'esnext.set.union': {
},
// TODO: Remove from `core-js@4`
Expand Down
9 changes: 9 additions & 0 deletions packages/core-js-compat/src/modules-by-versions.mjs
Expand Up @@ -162,4 +162,13 @@ export default {
'esnext.string.to-well-formed',
'web.self',
],
3.27: [
'esnext.set.difference.v2',
'esnext.set.intersection.v2',
'esnext.set.is-disjoint-from.v2',
'esnext.set.is-subset-of.v2',
'esnext.set.is-superset-of.v2',
'esnext.set.symmetric-difference.v2',
'esnext.set.union.v2',
],
};
61 changes: 61 additions & 0 deletions packages/core-js-pure/override/internals/set-helpers.js
@@ -0,0 +1,61 @@
var getBuiltIn = require('../internals/get-built-in');
var anObject = require('../internals/an-object');
var tryToString = require('../internals/try-to-string');
var iterateSimple = require('../internals/iterate-simple');

var Set = getBuiltIn('Set');
var SetPrototype = Set.prototype;
var $TypeError = TypeError;

var aSet = function (it) {
anObject(it);
if ('size' in it && 'has' in it && 'add' in it && 'delete' in it && 'keys' in it) return it;
throw $TypeError(tryToString(it) + ' is not a set');
};

var add = function (set, it) {
return set.add(it);
};

var remove = function (set, it) {
return set['delete'](it);
};

var forEach = function (set, fn) {
set.forEach(fn);
};

var has = function (set, it) {
return set.has(it);
};

var size = function (set) {
return set.size;
};

var clone = function (set) {
var result = new Set();
forEach(set, function (it) {
add(result, it);
});
return result;
};

var iterate = function (set, fn) {
var iterator = set.keys();
return iterateSimple(iterator, fn, iterator.next);
};

module.exports = {
Set: Set,
aSet: aSet,
add: add,
remove: remove,
forEach: forEach,
has: has,
size: size,
clone: clone,
iterate: iterate,
$has: SetPrototype.has,
$keys: SetPrototype.keys
};
@@ -0,0 +1,3 @@
module.exports = function () {
return false;
};
5 changes: 5 additions & 0 deletions packages/core-js/actual/set/difference.js
@@ -0,0 +1,5 @@
require('../../modules/es.set');
require('../../modules/esnext.set.difference.v2');
var entryUnbind = require('../../internals/entry-unbind');

module.exports = entryUnbind('Set', 'difference');
7 changes: 7 additions & 0 deletions packages/core-js/actual/set/index.js
@@ -1,3 +1,10 @@
var parent = require('../../stable/set');
require('../../modules/esnext.set.difference.v2');
require('../../modules/esnext.set.intersection.v2');
require('../../modules/esnext.set.is-disjoint-from.v2');
require('../../modules/esnext.set.is-subset-of.v2');
require('../../modules/esnext.set.is-superset-of.v2');
require('../../modules/esnext.set.symmetric-difference.v2');
require('../../modules/esnext.set.union.v2');

module.exports = parent;
5 changes: 5 additions & 0 deletions packages/core-js/actual/set/intersection.js
@@ -0,0 +1,5 @@
require('../../modules/es.set');
require('../../modules/esnext.set.intersection.v2');
var entryUnbind = require('../../internals/entry-unbind');

module.exports = entryUnbind('Set', 'intersection');
5 changes: 5 additions & 0 deletions packages/core-js/actual/set/is-disjoint-from.js
@@ -0,0 +1,5 @@
require('../../modules/es.set');
require('../../modules/esnext.set.is-disjoint-from.v2');
var entryUnbind = require('../../internals/entry-unbind');

module.exports = entryUnbind('Set', 'isDisjointFrom');
5 changes: 5 additions & 0 deletions packages/core-js/actual/set/is-subset-of.js
@@ -0,0 +1,5 @@
require('../../modules/es.set');
require('../../modules/esnext.set.is-subset-of.v2');
var entryUnbind = require('../../internals/entry-unbind');

module.exports = entryUnbind('Set', 'isSubsetOf');
5 changes: 5 additions & 0 deletions packages/core-js/actual/set/is-superset-of.js
@@ -0,0 +1,5 @@
require('../../modules/es.set');
require('../../modules/esnext.set.is-superset-of.v2');
var entryUnbind = require('../../internals/entry-unbind');

module.exports = entryUnbind('Set', 'isSupersetOf');
5 changes: 5 additions & 0 deletions packages/core-js/actual/set/symmetric-difference.js
@@ -0,0 +1,5 @@
require('../../modules/es.set');
require('../../modules/esnext.set.symmetric-difference.v2');
var entryUnbind = require('../../internals/entry-unbind');

module.exports = entryUnbind('Set', 'symmetricDifference');
5 changes: 5 additions & 0 deletions packages/core-js/actual/set/union.js
@@ -0,0 +1,5 @@
require('../../modules/es.set');
require('../../modules/esnext.set.union.v2');
var entryUnbind = require('../../internals/entry-unbind');

module.exports = entryUnbind('Set', 'union');
2 changes: 1 addition & 1 deletion packages/core-js/full/set/difference.js
@@ -1,5 +1,5 @@
require('../../actual/set/difference');
require('../../modules/es.array.iterator');
require('../../modules/es.set');
require('../../modules/es.string.iterator');
require('../../modules/esnext.set.difference');
require('../../modules/web.dom-collections.iterator');
Expand Down
2 changes: 1 addition & 1 deletion packages/core-js/full/set/intersection.js
@@ -1,5 +1,5 @@
require('../../actual/set/intersection');
require('../../modules/es.array.iterator');
require('../../modules/es.set');
require('../../modules/es.string.iterator');
require('../../modules/esnext.set.intersection');
require('../../modules/web.dom-collections.iterator');
Expand Down
2 changes: 1 addition & 1 deletion packages/core-js/full/set/is-disjoint-from.js
@@ -1,5 +1,5 @@
require('../../actual/set/is-disjoint-from');
require('../../modules/es.array.iterator');
require('../../modules/es.set');
require('../../modules/es.string.iterator');
require('../../modules/esnext.set.is-disjoint-from');
require('../../modules/web.dom-collections.iterator');
Expand Down
2 changes: 1 addition & 1 deletion packages/core-js/full/set/is-subset-of.js
@@ -1,5 +1,5 @@
require('../../actual/set/is-subset-of');
require('../../modules/es.array.iterator');
require('../../modules/es.set');
require('../../modules/es.string.iterator');
require('../../modules/esnext.set.is-subset-of');
require('../../modules/web.dom-collections.iterator');
Expand Down
2 changes: 1 addition & 1 deletion packages/core-js/full/set/is-superset-of.js
@@ -1,5 +1,5 @@
require('../../actual/set/is-superset-of');
require('../../modules/es.array.iterator');
require('../../modules/es.set');
require('../../modules/es.string.iterator');
require('../../modules/esnext.set.is-superset-of');
require('../../modules/web.dom-collections.iterator');
Expand Down
2 changes: 1 addition & 1 deletion packages/core-js/full/set/symmetric-difference.js
@@ -1,5 +1,5 @@
require('../../actual/set/symmetric-difference');
require('../../modules/es.array.iterator');
require('../../modules/es.set');
require('../../modules/es.string.iterator');
require('../../modules/esnext.set.symmetric-difference');
require('../../modules/web.dom-collections.iterator');
Expand Down
2 changes: 1 addition & 1 deletion packages/core-js/full/set/union.js
@@ -1,5 +1,5 @@
require('../../actual/set/union');
require('../../modules/es.array.iterator');
require('../../modules/es.set');
require('../../modules/es.string.iterator');
require('../../modules/esnext.set.union');
require('../../modules/web.dom-collections.iterator');
Expand Down
38 changes: 38 additions & 0 deletions packages/core-js/internals/get-set-record.js
@@ -0,0 +1,38 @@
var aCallable = require('../internals/a-callable');
var anObject = require('../internals/an-object');
var call = require('../internals/function-call');
var toIntegerOrInfinity = require('../internals/to-integer-or-infinity');

var $TypeError = TypeError;

var SetRecord = function (set, size, has, keys) {
this.set = set;
this.size = size;
this.has = has;
this.keys = keys;
};

SetRecord.prototype = {
getIterator: function () {
return anObject(call(this.keys, this.set));
},
includes: function (it) {
return call(this.has, this.set, it);
}
};

// `GetSetRecord` abstract operation
// https://tc39.es/proposal-set-methods/#sec-getsetrecord
module.exports = function (obj) {
anObject(obj);
var numSize = +obj.size;
// NOTE: If size is undefined, then numSize will be NaN
// eslint-disable-next-line no-self-compare -- NaN check
if (numSize != numSize) throw $TypeError('Invalid size');
return new SetRecord(
obj,
toIntegerOrInfinity(numSize),
aCallable(obj.has),
aCallable(obj.keys)
);
};

0 comments on commit 541c979

Please sign in to comment.