Skip to content
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

Update Set methods proposal #1150

Merged
merged 11 commits into from
Dec 11, 2022
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = function () {
return false;
};
5 changes: 5 additions & 0 deletions packages/core-js/actual/set/difference.js
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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)
);
};
Loading