Skip to content

Commit 4be4647

Browse files
authored
Add Map and WeakMap upsert methods (#1156)
Implement the new methods from https://github.com/tc39/proposal-upsert: - Map.prototype.getOrInsert - Map.prototype.getOrInsertComputed - WeakMap.prototype.getOrInsert - WeakMap.prototype.getOrInsertComputed
1 parent 632601d commit 4be4647

File tree

2 files changed

+48
-1
lines changed

2 files changed

+48
-1
lines changed

quickjs.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49057,6 +49057,45 @@ static JSValue js_map_get(JSContext *ctx, JSValueConst this_val,
4905749057
return js_dup(mr->value);
4905849058
}
4905949059

49060+
static JSValue js_map_getOrInsert(JSContext *ctx, JSValueConst this_val,
49061+
int argc, JSValueConst *argv, int magic)
49062+
{
49063+
bool computed = magic & 1;
49064+
JSClassID class_id = magic >> 1;
49065+
JSMapState *s = JS_GetOpaque2(ctx, this_val, class_id);
49066+
JSMapRecord *mr;
49067+
JSValueConst key;
49068+
JSValue value;
49069+
49070+
if (!s)
49071+
return JS_EXCEPTION;
49072+
if (computed && !JS_IsFunction(ctx, argv[1]))
49073+
return JS_ThrowTypeError(ctx, "not a function");
49074+
key = map_normalize_key_const(ctx, argv[0]);
49075+
if (s->is_weak && !is_valid_weakref_target(key))
49076+
return JS_ThrowTypeError(ctx, "invalid value used as WeakMap key");
49077+
mr = map_find_record(ctx, s, key);
49078+
if (!mr) {
49079+
if (computed) {
49080+
value = JS_Call(ctx, argv[1], JS_UNDEFINED, 1, &key);
49081+
if (JS_IsException(value))
49082+
return JS_EXCEPTION;
49083+
mr = map_find_record(ctx, s, key);
49084+
if (mr)
49085+
map_delete_record(ctx->rt, s, mr);
49086+
} else {
49087+
value = js_dup(argv[1]);
49088+
}
49089+
mr = map_add_record(ctx, s, key);
49090+
if (!mr) {
49091+
JS_FreeValue(ctx, value);
49092+
return JS_EXCEPTION;
49093+
}
49094+
mr->value = value;
49095+
}
49096+
return js_dup(mr->value);
49097+
}
49098+
4906049099
static JSValue js_map_has(JSContext *ctx, JSValueConst this_val,
4906149100
int argc, JSValueConst *argv, int magic)
4906249101
{
@@ -50115,6 +50154,10 @@ static const JSCFunctionListEntry js_set_funcs[] = {
5011550154
static const JSCFunctionListEntry js_map_proto_funcs[] = {
5011650155
JS_CFUNC_MAGIC_DEF("set", 2, js_map_set, 0 ),
5011750156
JS_CFUNC_MAGIC_DEF("get", 1, js_map_get, 0 ),
50157+
JS_CFUNC_MAGIC_DEF("getOrInsert", 2, js_map_getOrInsert,
50158+
JS_CLASS_MAP<<1 | /*computed*/false ),
50159+
JS_CFUNC_MAGIC_DEF("getOrInsertComputed", 2, js_map_getOrInsert,
50160+
JS_CLASS_MAP<<1 | /*computed*/true ),
5011850161
JS_CFUNC_MAGIC_DEF("has", 1, js_map_has, 0 ),
5011950162
JS_CFUNC_MAGIC_DEF("delete", 1, js_map_delete, 0 ),
5012050163
JS_CFUNC_MAGIC_DEF("clear", 0, js_map_clear, 0 ),
@@ -50161,6 +50204,10 @@ static const JSCFunctionListEntry js_set_iterator_proto_funcs[] = {
5016150204
static const JSCFunctionListEntry js_weak_map_proto_funcs[] = {
5016250205
JS_CFUNC_MAGIC_DEF("set", 2, js_map_set, MAGIC_WEAK ),
5016350206
JS_CFUNC_MAGIC_DEF("get", 1, js_map_get, MAGIC_WEAK ),
50207+
JS_CFUNC_MAGIC_DEF("getOrInsert", 2, js_map_getOrInsert,
50208+
JS_CLASS_WEAKMAP<<1 | /*computed*/false ),
50209+
JS_CFUNC_MAGIC_DEF("getOrInsertComputed", 2, js_map_getOrInsert,
50210+
JS_CLASS_WEAKMAP<<1 | /*computed*/true ),
5016450211
JS_CFUNC_MAGIC_DEF("has", 1, js_map_has, MAGIC_WEAK ),
5016550212
JS_CFUNC_MAGIC_DEF("delete", 1, js_map_delete, MAGIC_WEAK ),
5016650213
JS_PROP_STRING_DEF("[Symbol.toStringTag]", "WeakMap", JS_PROP_CONFIGURABLE ),

test262.conf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ Uint32Array
226226
Uint8Array
227227
uint8array-base64=skip
228228
Uint8ClampedArray
229-
upsert=skip
229+
upsert
230230
WeakMap
231231
WeakRef
232232
WeakSet

0 commit comments

Comments
 (0)