Skip to content

Commit e3e9f37

Browse files
committed
update Map upsert proposal to the new API
tc39/proposal-upsert#58
1 parent 04c068e commit e3e9f37

25 files changed

+190
-21
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,13 @@
2929
- `Math.sumPrecise`
3030
- Moved to stage 3, [October 2024 TC39 meeting](https://x.com/robpalmer2/status/1843829675036160179)
3131
- Added `/actual/` namespace entries, unconditional forced replacement changed to feature detection
32+
- [`Map` upsert stage 2 proposal](https://github.com/tc39/proposal-upsert):
33+
- [Updated to the new API following the October 2024 TC39 meeting](https://github.com/tc39/proposal-upsert/pull/58)
34+
- Added built-ins:
35+
- `Map.prototype.getOrInsert`
36+
- `Map.prototype.getOrInsertComputed`
37+
- `WeakMap.prototype.getOrInsert`
38+
- `WeakMap.prototype.getOrInsertComputed`
3239
- [Extractors proposal](https://github.com/tc39/proposal-extractors) moved to stage 2, [October 2024 TC39 meeting](https://github.com/tc39/proposals/commit/11bc489049fc5ce59b21e98a670a84f153a29a80)
3340
- Usage of `@@species` pattern removed from `%TypedArray%` and `ArrayBuffer` methods, [tc39/ecma262/3450](https://github.com/tc39/ecma262/pull/3450):
3441
- Built-ins:

README.md

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ structuredClone(new Set([1, 2, 3])); // => new Set([1, 2, 3])
171171
- [Stage 2 proposals](#stage-2-proposals)
172172
- [`AsyncIterator` helpers](#asynciterator-helpers)
173173
- [`Iterator.range`](#iteratorrange)
174-
- [`Map.prototype.emplace`](#mapprototypeemplace)
174+
- [`Map` upsert](#map-upsert)
175175
- [`Array.isTemplateObject`](#arrayistemplateobject)
176176
- [`String.dedent`](#stringdedent)
177177
- [`Symbol` predicates](#symbol-predicates)
@@ -2755,32 +2755,40 @@ for (const i of Iterator.range(1, 10, { step: 3, inclusive: true })) {
27552755
console.log(i); // => 1, 4, 7, 10
27562756
}
27572757
```
2758-
##### [`Map.prototype.emplace`](https://github.com/thumbsupep/proposal-upsert)[](#index)
2759-
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)
2758+
##### [`Map` upsert](https://github.com/thumbsupep/proposal-upsert)[](#index)
2759+
Modules [`esnext.map.get-or-insert`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.map.get-or-insert.js), [`esnext.map.get-or-insert-computed`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.map.get-or-insert-computed.js), [`esnext.weak-map.get-or-insert`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.weak-map.get-or-insert.js) and [`esnext.weak-map.get-or-insert-computed`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.weak-map.get-or-insert-computed.js)
27602760
```ts
27612761
class Map {
2762-
emplace(key: any, { update: (value: any, key: any, handler: object) => updated: any, insert: (key: any, handler: object) => value: any): updated | value;
2762+
getOrInsert(key: any, value: any): any;
2763+
getOrInsertComputed(key: any, (key: any) => value: any): any;
27632764
}
27642765

27652766
class WeakMap {
2766-
emplace(key: any, { update: (value: any, key: any, handler: object) => updated: any, insert: (key: any, handler: object) => value: any): updated | value;
2767+
getOrInsert(key: any, value: any): any;
2768+
getOrInsertComputed(key: any, (key: any) => value: any): any;
27672769
}
27682770
```
27692771
[*CommonJS entry points:*](#commonjs-api)
27702772
```
2771-
core-js/proposals/map-upsert-stage-2
2772-
core-js(-pure)/full/map/emplace
2773-
core-js(-pure)/full/weak-map/emplace
2773+
core-js/proposals/map-upsert-v4
2774+
core-js(-pure)/full/map/get-or-insert
2775+
core-js(-pure)/full/map/get-or-insert-computed
2776+
core-js(-pure)/full/weak-map/get-or-insert
2777+
core-js(-pure)/full/weak-map/get-or-insert-computed
27742778
```
2775-
[*Examples*](https://is.gd/ty5I2v):
2779+
[*Examples*](https://tinyurl.com/2a54u5ux):
27762780
```js
2777-
const map = new Map([['a', 2]]);
2781+
const map = new Map([['a', 1]]);
27782782

2779-
map.emplace('a', { update: it => it ** 2, insert: () => 3 }); // => 4
2783+
map.getOrInsert('a', 2); // => 1
27802784

2781-
map.emplace('b', { update: it => it ** 2, insert: () => 3 }); // => 3
2785+
map.getOrInsert('b', 3); // => 3
27822786

2783-
console.log(map); // => Map { 'a': 4, 'b': 3 }
2787+
map.getOrInsertComputed('a', key => key); // => 1
2788+
2789+
map.getOrInsertComputed('c', key => key); // => 'c'
2790+
2791+
console.log(map); // => Map { 'a': 1, 'b': 3, 'c': 'c' }
27842792
```
27852793
##### [`Array.isTemplateObject`](https://github.com/tc39/proposal-array-is-template-object)[](#index)
27862794
Module [`esnext.array.is-template-object`](https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/esnext.array.is-template-object.js)

packages/core-js-compat/src/data.mjs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2298,6 +2298,7 @@ export const data = {
22982298
},
22992299
'esnext.map.delete-all': {
23002300
},
2301+
// TODO: Remove from `core-js@4`
23012302
'esnext.map.emplace': {
23022303
},
23032304
'esnext.map.every': {
@@ -2310,6 +2311,10 @@ export const data = {
23102311
},
23112312
'esnext.map.from': {
23122313
},
2314+
'esnext.map.get-or-insert': {
2315+
},
2316+
'esnext.map.get-or-insert-computed': {
2317+
},
23132318
// TODO: Remove from `core-js@4`
23142319
'esnext.map.group-by': null,
23152320
'esnext.map.includes': {
@@ -2619,8 +2624,13 @@ export const data = {
26192624
},
26202625
'esnext.weak-map.of': {
26212626
},
2627+
// TODO: Remove from `core-js@4`
26222628
'esnext.weak-map.emplace': {
26232629
},
2630+
'esnext.weak-map.get-or-insert': {
2631+
},
2632+
'esnext.weak-map.get-or-insert-computed': {
2633+
},
26242634
// TODO: Remove from `core-js@4`
26252635
'esnext.weak-map.upsert': {
26262636
},

packages/core-js-compat/src/modules-by-versions.mjs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,5 +268,9 @@ export default {
268268
'es.iterator.take',
269269
'es.iterator.to-array',
270270
'es.promise.try',
271+
'esnext.map.get-or-insert',
272+
'esnext.map.get-or-insert-computed',
273+
'esnext.weak-map.get-or-insert',
274+
'esnext.weak-map.get-or-insert-computed',
271275
],
272276
};

packages/core-js/full/map/from.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ require('../../modules/esnext.map.every');
1010
require('../../modules/esnext.map.filter');
1111
require('../../modules/esnext.map.find');
1212
require('../../modules/esnext.map.find-key');
13+
require('../../modules/esnext.map.get-or-insert');
14+
require('../../modules/esnext.map.get-or-insert-computed');
1315
require('../../modules/esnext.map.includes');
1416
require('../../modules/esnext.map.key-of');
1517
require('../../modules/esnext.map.map-keys');
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
'use strict';
2+
require('../../modules/es.map');
3+
require('../../modules/esnext.map.get-or-insert-computed');
4+
var entryUnbind = require('../../internals/entry-unbind');
5+
6+
module.exports = entryUnbind('Map', 'getOrInsertComputed');
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
'use strict';
2+
require('../../modules/es.map');
3+
require('../../modules/esnext.map.get-or-insert');
4+
var entryUnbind = require('../../internals/entry-unbind');
5+
6+
module.exports = entryUnbind('Map', 'getOrInsert');

packages/core-js/full/map/group-by.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ require('../../modules/esnext.map.every');
66
require('../../modules/esnext.map.filter');
77
require('../../modules/esnext.map.find');
88
require('../../modules/esnext.map.find-key');
9+
require('../../modules/esnext.map.get-or-insert');
10+
require('../../modules/esnext.map.get-or-insert-computed');
911
require('../../modules/esnext.map.includes');
1012
require('../../modules/esnext.map.key-of');
1113
require('../../modules/esnext.map.map-keys');

packages/core-js/full/map/index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,16 @@
22
var parent = require('../../actual/map');
33
require('../../modules/esnext.map.from');
44
require('../../modules/esnext.map.of');
5+
require('../../modules/esnext.map.key-by');
56
require('../../modules/esnext.map.delete-all');
67
require('../../modules/esnext.map.emplace');
78
require('../../modules/esnext.map.every');
89
require('../../modules/esnext.map.filter');
910
require('../../modules/esnext.map.find');
1011
require('../../modules/esnext.map.find-key');
1112
require('../../modules/esnext.map.includes');
12-
require('../../modules/esnext.map.key-by');
13+
require('../../modules/esnext.map.get-or-insert');
14+
require('../../modules/esnext.map.get-or-insert-computed');
1315
require('../../modules/esnext.map.key-of');
1416
require('../../modules/esnext.map.map-keys');
1517
require('../../modules/esnext.map.map-values');

packages/core-js/full/map/key-by.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ require('../../modules/esnext.map.every');
88
require('../../modules/esnext.map.filter');
99
require('../../modules/esnext.map.find');
1010
require('../../modules/esnext.map.find-key');
11+
require('../../modules/esnext.map.get-or-insert');
12+
require('../../modules/esnext.map.get-or-insert-computed');
1113
require('../../modules/esnext.map.includes');
1214
require('../../modules/esnext.map.key-of');
1315
require('../../modules/esnext.map.map-keys');

packages/core-js/full/map/of.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ require('../../modules/esnext.map.every');
99
require('../../modules/esnext.map.filter');
1010
require('../../modules/esnext.map.find');
1111
require('../../modules/esnext.map.find-key');
12+
require('../../modules/esnext.map.get-or-insert');
13+
require('../../modules/esnext.map.get-or-insert-computed');
1214
require('../../modules/esnext.map.includes');
1315
require('../../modules/esnext.map.key-of');
1416
require('../../modules/esnext.map.map-keys');

packages/core-js/full/weak-map/from.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ require('../../modules/es.weak-map');
66
require('../../modules/esnext.weak-map.from');
77
require('../../modules/esnext.weak-map.delete-all');
88
require('../../modules/esnext.weak-map.emplace');
9+
require('../../modules/esnext.weak-map.get-or-insert');
10+
require('../../modules/esnext.weak-map.get-or-insert-computed');
911
require('../../modules/web.dom-collections.iterator');
1012
var path = require('../../internals/path');
1113

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
'use strict';
2+
require('../../modules/es.weak-map');
3+
require('../../modules/esnext.weak-map.get-or-insert-computed');
4+
var entryUnbind = require('../../internals/entry-unbind');
5+
6+
module.exports = entryUnbind('WeakMap', 'getOrInsertComputed');
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
'use strict';
2+
require('../../modules/es.weak-map');
3+
require('../../modules/esnext.weak-map.get-or-insert');
4+
var entryUnbind = require('../../internals/entry-unbind');
5+
6+
module.exports = entryUnbind('WeakMap', 'getOrInsert');

packages/core-js/full/weak-map/index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
'use strict';
22
var parent = require('../../actual/weak-map');
33
require('../../modules/es.string.iterator');
4-
require('../../modules/esnext.weak-map.emplace');
54
require('../../modules/esnext.weak-map.from');
65
require('../../modules/esnext.weak-map.of');
6+
require('../../modules/esnext.weak-map.emplace');
7+
require('../../modules/esnext.weak-map.get-or-insert');
8+
require('../../modules/esnext.weak-map.get-or-insert-computed');
79
require('../../modules/esnext.weak-map.delete-all');
810
// TODO: remove from `core-js@4`
911
require('../../modules/esnext.weak-map.upsert');

packages/core-js/full/weak-map/of.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ require('../../modules/es.weak-map');
55
require('../../modules/esnext.weak-map.of');
66
require('../../modules/esnext.weak-map.delete-all');
77
require('../../modules/esnext.weak-map.emplace');
8+
require('../../modules/esnext.weak-map.get-or-insert');
9+
require('../../modules/esnext.weak-map.get-or-insert-computed');
810
var path = require('../../internals/path');
911

1012
module.exports = path.WeakMap.of;
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
'use strict';
2+
var $ = require('../internals/export');
3+
var aCallable = require('../internals/a-callable');
4+
var aMap = require('../internals/a-map');
5+
var MapHelpers = require('../internals/map-helpers');
6+
7+
var get = MapHelpers.get;
8+
var has = MapHelpers.has;
9+
var set = MapHelpers.set;
10+
11+
// `Map.prototype.getOrInsertComputed` method
12+
// https://github.com/tc39/proposal-upsert
13+
$({ target: 'Map', proto: true, real: true, forced: true }, {
14+
getOrInsertComputed: function getOrInsertComputed(key, callbackfn) {
15+
aMap(this);
16+
aCallable(callbackfn);
17+
if (has(this, key)) return get(this, key);
18+
var value = callbackfn(key);
19+
set(this, key, value);
20+
return value;
21+
}
22+
});
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
'use strict';
2+
var $ = require('../internals/export');
3+
var aMap = require('../internals/a-map');
4+
var MapHelpers = require('../internals/map-helpers');
5+
6+
var get = MapHelpers.get;
7+
var has = MapHelpers.has;
8+
var set = MapHelpers.set;
9+
10+
// `Map.prototype.getOrInsert` method
11+
// https://github.com/tc39/proposal-upsert
12+
$({ target: 'Map', proto: true, real: true, forced: true }, {
13+
getOrInsert: function getOrInsert(key, value) {
14+
if (has(aMap(this), key)) return get(this, key);
15+
set(this, key, value);
16+
return value;
17+
}
18+
});
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
'use strict';
2+
var $ = require('../internals/export');
3+
var aCallable = require('../internals/a-callable');
4+
var aWeakMap = require('../internals/a-weak-map');
5+
var WeakMapHelpers = require('../internals/weak-map-helpers');
6+
7+
var get = WeakMapHelpers.get;
8+
var has = WeakMapHelpers.has;
9+
var set = WeakMapHelpers.set;
10+
11+
// `WeakMap.prototype.getOrInsertComputed` method
12+
// https://github.com/tc39/proposal-upsert
13+
$({ target: 'WeakMap', proto: true, real: true, forced: true }, {
14+
getOrInsertComputed: function getOrInsertComputed(key, callbackfn) {
15+
aWeakMap(this);
16+
aCallable(callbackfn);
17+
if (has(this, key)) return get(this, key);
18+
var value = callbackfn(key);
19+
set(this, key, value);
20+
return value;
21+
}
22+
});
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
'use strict';
2+
var $ = require('../internals/export');
3+
var aWeakMap = require('../internals/a-weak-map');
4+
var WeakMapHelpers = require('../internals/weak-map-helpers');
5+
6+
var get = WeakMapHelpers.get;
7+
var has = WeakMapHelpers.has;
8+
var set = WeakMapHelpers.set;
9+
10+
// `WeakMap.prototype.getOrInsert` method
11+
// https://github.com/tc39/proposal-upsert
12+
$({ target: 'WeakMap', proto: true, real: true, forced: true }, {
13+
getOrInsert: function getOrInsert(key, value) {
14+
if (has(aWeakMap(this), key)) return get(this, key);
15+
set(this, key, value);
16+
return value;
17+
}
18+
});
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
'use strict';
2+
// https://github.com/tc39/proposal-upsert
3+
require('../modules/esnext.map.get-or-insert');
4+
require('../modules/esnext.map.get-or-insert-computed');
5+
require('../modules/esnext.weak-map.get-or-insert');
6+
require('../modules/esnext.weak-map.get-or-insert-computed');

packages/core-js/stage/2.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ require('../proposals/array-is-template-object');
55
require('../proposals/async-iterator-helpers');
66
require('../proposals/extractors');
77
require('../proposals/iterator-range');
8-
require('../proposals/map-upsert-stage-2');
8+
require('../proposals/map-upsert-v4');
99
require('../proposals/string-dedent');
1010
require('../proposals/symbol-predicates-v2');
1111
// TODO: Obsolete versions, remove from `core-js@4`
@@ -14,6 +14,7 @@ require('../proposals/async-explicit-resource-management');
1414
require('../proposals/decorators');
1515
require('../proposals/decorator-metadata');
1616
require('../proposals/iterator-helpers');
17+
require('../proposals/map-upsert-stage-2');
1718
require('../proposals/set-methods');
1819
require('../proposals/symbol-predicates');
1920
require('../proposals/using-statement');

tests/compat-data/tests-coverage.mjs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const ignore = new Set([
2929
'esnext.function.un-this',
3030
'esnext.iterator.as-indexed-pairs',
3131
'esnext.iterator.indexed',
32+
'esnext.map.emplace',
3233
'esnext.map.update-or-insert',
3334
'esnext.map.upsert',
3435
'esnext.math.iaddh',
@@ -71,6 +72,7 @@ const ignore = new Set([
7172
'esnext.typed-array.filter-out',
7273
'esnext.typed-array.group-by',
7374
'esnext.typed-array.to-spliced',
75+
'esnext.weak-map.emplace',
7476
'esnext.weak-map.upsert',
7577
'web.url-search-params',
7678
'web.url',

tests/compat/tests.js

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1699,9 +1699,6 @@ GLOBAL.tests = {
16991699
'esnext.map.delete-all': function () {
17001700
return Map.prototype.deleteAll;
17011701
},
1702-
'esnext.map.emplace': function () {
1703-
return Map.prototype.emplace;
1704-
},
17051702
'esnext.map.every': function () {
17061703
return Map.prototype.every;
17071704
},
@@ -1717,6 +1714,12 @@ GLOBAL.tests = {
17171714
'esnext.map.from': function () {
17181715
return Map.from;
17191716
},
1717+
'esnext.map.get-or-insert': function () {
1718+
return Map.prototype.getOrInsert;
1719+
},
1720+
'esnext.map.get-or-insert-computed': function () {
1721+
return Map.prototype.getOrInsertComputed;
1722+
},
17201723
'esnext.map.includes': function () {
17211724
return Map.prototype.includes;
17221725
},
@@ -1875,8 +1878,11 @@ GLOBAL.tests = {
18751878
'esnext.weak-map.delete-all': function () {
18761879
return WeakMap.prototype.deleteAll;
18771880
},
1878-
'esnext.weak-map.emplace': function () {
1879-
return WeakMap.prototype.emplace;
1881+
'esnext.weak-map.get-or-insert': function () {
1882+
return WeakMap.prototype.getOrInsert;
1883+
},
1884+
'esnext.weak-map.get-or-insert-computed': function () {
1885+
return WeakMap.prototype.getOrInsertComputed;
18801886
},
18811887
'esnext.weak-map.from': function () {
18821888
return WeakMap.from;

0 commit comments

Comments
 (0)