Skip to content

Commit 5e6b127

Browse files
committed
add proposal-upsert methods to lib.esnext.collection
1 parent d3be7e1 commit 5e6b127

29 files changed

Lines changed: 1061 additions & 77 deletions

src/compiler/utilities.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1581,6 +1581,10 @@ export const getScriptTargetFeatures: () => ScriptTargetFeatures = /* @__PURE__
15811581
"keys",
15821582
"values",
15831583
],
1584+
esnext: [
1585+
"getOrInsert",
1586+
"getOrInsertComputed",
1587+
],
15841588
})),
15851589
MapConstructor: new Map(Object.entries({
15861590
es2024: [
@@ -1635,6 +1639,10 @@ export const getScriptTargetFeatures: () => ScriptTargetFeatures = /* @__PURE__
16351639
"keys",
16361640
"values",
16371641
],
1642+
esnext: [
1643+
"getOrInsert",
1644+
"getOrInsertComputed",
1645+
],
16381646
})),
16391647
WeakSet: new Map(Object.entries({
16401648
es2015: [

src/lib/esnext.collection.d.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,35 @@
11
/// <reference lib="es2024.collection" />
22

3+
interface Map<K, V> {
4+
/**
5+
* Returns a specified element from the Map object.
6+
* If no element is associated with the specified key, a new element with the value `defaultValue` will be inserted into the Map and returned.
7+
* @returns The element associated with the specified key, which will be `defaultValue` if no element previously existed.
8+
*/
9+
getOrInsert(key: K, defaultValue: V): V;
10+
/**
11+
* Returns a specified element from the Map object.
12+
* If no element is associated with the specified key, the result of passing the specified key to the `callback` function will be inserted into the Map and returned.
13+
* @returns The element associated with the specific key, which will be the newly computed value if no element previously existed.
14+
*/
15+
getOrInsertComputed(key: K, callback: (key: K) => V): V;
16+
}
17+
18+
interface WeakMap<K extends WeakKey, V> {
19+
/**
20+
* Returns a specified element from the WeakMap object.
21+
* If no element is associated with the specified key, a new element with the value `defaultValue` will be inserted into the WeakMap and returned.
22+
* @returns The element associated with the specified key, which will be `defaultValue` if no element previously existed.
23+
*/
24+
getOrInsert(key: K, defaultValue: V): V;
25+
/**
26+
* Returns a specified element from the WeakMap object.
27+
* If no element is associated with the specified key, the result of passing the specified key to the `callback` function will be inserted into the WeakMap and returned.
28+
* @returns The element associated with the specific key, which will be the newly computed value if no element previously existed.
29+
*/
30+
getOrInsertComputed(key: K, callback: (key: K) => V): V;
31+
}
32+
333
interface ReadonlySetLike<T> {
434
/**
535
* Despite its name, returns an iterator of the values in the set-like.

tests/baselines/reference/acceptSymbolAsWeakType.symbols

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ ws.delete(s);
3030

3131
const wm = new WeakMap([[s, false]]);
3232
>wm : Symbol(wm, Decl(acceptSymbolAsWeakType.ts, 7, 5))
33-
>WeakMap : Symbol(WeakMap, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
33+
>WeakMap : Symbol(WeakMap, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.esnext.collection.d.ts, --, --))
3434
>s : Symbol(s, Decl(acceptSymbolAsWeakType.ts, 0, 5))
3535

3636
wm.set(s, true);

tests/baselines/reference/awaitUsingDeclarationsWithIteratorObject.symbols

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ async function f() {
5555
await using it5 = new Map<string, string>().entries();
5656
>it5 : Symbol(it5, Decl(awaitUsingDeclarationsWithIteratorObject.ts, 15, 15))
5757
>new Map<string, string>().entries : Symbol(Map.entries, Decl(lib.es2015.iterable.d.ts, --, --))
58-
>Map : Symbol(Map, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
58+
>Map : Symbol(Map, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.esnext.collection.d.ts, --, --))
5959
>entries : Symbol(Map.entries, Decl(lib.es2015.iterable.d.ts, --, --))
6060

6161
await using it6 = new Set<string>().keys();

tests/baselines/reference/builtinIteratorReturn(strictbuiltiniteratorreturn=false).symbols

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ declare const array: number[];
66

77
declare const map: Map<string, number>;
88
>map : Symbol(map, Decl(builtinIteratorReturn.ts, 1, 13))
9-
>Map : Symbol(Map, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
9+
>Map : Symbol(Map, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.esnext.collection.d.ts, --, --))
1010

1111
declare const set: Set<number>;
1212
>set : Symbol(set, Decl(builtinIteratorReturn.ts, 2, 13))

tests/baselines/reference/builtinIteratorReturn(strictbuiltiniteratorreturn=true).symbols

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ declare const array: number[];
66

77
declare const map: Map<string, number>;
88
>map : Symbol(map, Decl(builtinIteratorReturn.ts, 1, 13))
9-
>Map : Symbol(Map, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
9+
>Map : Symbol(Map, Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.collection.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.esnext.collection.d.ts, --, --))
1010

1111
declare const set: Set<number>;
1212
>set : Symbol(set, Decl(builtinIteratorReturn.ts, 2, 13))

tests/baselines/reference/esNextWeakRefs_IterableWeakMap.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,23 @@ export class IterableWeakMap<K extends object, V> implements WeakMap<K, V> {
5050
return this.#weakMap.get(key)?.value;
5151
}
5252

53+
getOrInsert(key: K, defaultValue: V): V {
54+
if (!this.has(key)) {
55+
this.set(key, defaultValue);
56+
return defaultValue;
57+
}
58+
return this.get(key)!;
59+
}
60+
61+
getOrInsertComputed(key: K, callback: (key: K) => V): V {
62+
if (!this.has(key)) {
63+
const value = callback(key);
64+
this.set(key, value);
65+
return value;
66+
}
67+
return this.get(key)!;
68+
}
69+
5370
delete(key: K): boolean {
5471
const entry = this.#weakMap.get(key);
5572
if (entry === undefined) {
@@ -144,6 +161,21 @@ export class IterableWeakMap {
144161
get(key) {
145162
return this.#weakMap.get(key)?.value;
146163
}
164+
getOrInsert(key, defaultValue) {
165+
if (!this.has(key)) {
166+
this.set(key, defaultValue);
167+
return defaultValue;
168+
}
169+
return this.get(key);
170+
}
171+
getOrInsertComputed(key, callback) {
172+
if (!this.has(key)) {
173+
const value = callback(key);
174+
this.set(key, value);
175+
return value;
176+
}
177+
return this.get(key);
178+
}
147179
delete(key) {
148180
const entry = this.#weakMap.get(key);
149181
if (entry === undefined) {

0 commit comments

Comments
 (0)