mirror of
https://github.com/DoneJS-Runtime/quickjs-done-nextgen.git
synced 2025-01-09 17:43:15 +00:00
Add Set.prototype.symmetricDifference (#507)
This commit is contained in:
parent
61c8fe6fb0
commit
6ba2448751
2 changed files with 93 additions and 50 deletions
97
quickjs.c
97
quickjs.c
|
@ -46327,13 +46327,100 @@ fini:
|
||||||
return newset;
|
return newset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static JSValue js_set_symmetricDifference(JSContext *ctx, JSValue this_val,
|
||||||
|
int argc, JSValue *argv)
|
||||||
|
{
|
||||||
|
JSValue newset, item, iter, next, rv;
|
||||||
|
struct list_head *el;
|
||||||
|
JSMapState *s, *t;
|
||||||
|
JSMapRecord *mr;
|
||||||
|
int64_t size;
|
||||||
|
BOOL done, present;
|
||||||
|
|
||||||
|
s = JS_GetOpaque2(ctx, this_val, JS_CLASS_SET);
|
||||||
|
if (!s)
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
// order matters! they're JS-observable side effects
|
||||||
|
if (js_setlike_get_size(ctx, argv[0], &size) < 0)
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
if (js_setlike_get_has(ctx, argv[0], &rv) < 0)
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
JS_FreeValue(ctx, rv);
|
||||||
|
newset = js_map_constructor(ctx, JS_UNDEFINED, 0, NULL, MAGIC_SET);
|
||||||
|
if (JS_IsException(newset))
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
t = JS_GetOpaque(newset, JS_CLASS_SET);
|
||||||
|
iter = JS_UNDEFINED;
|
||||||
|
next = JS_UNDEFINED;
|
||||||
|
// can't clone this_val using js_map_constructor(),
|
||||||
|
// test262 mandates we don't call the .add method
|
||||||
|
list_for_each(el, &s->records) {
|
||||||
|
mr = list_entry(el, JSMapRecord, link);
|
||||||
|
if (mr->empty)
|
||||||
|
continue;
|
||||||
|
mr = map_add_record(ctx, t, js_dup(mr->key));
|
||||||
|
if (!mr)
|
||||||
|
goto exception;
|
||||||
|
mr->value = JS_UNDEFINED;
|
||||||
|
}
|
||||||
|
iter = JS_GetProperty(ctx, argv[0], JS_ATOM_keys);
|
||||||
|
if (JS_IsException(iter))
|
||||||
|
goto exception;
|
||||||
|
iter = JS_CallFree(ctx, iter, argv[0], 0, NULL);
|
||||||
|
if (JS_IsException(iter))
|
||||||
|
goto exception;
|
||||||
|
next = JS_GetProperty(ctx, iter, JS_ATOM_next);
|
||||||
|
if (JS_IsException(next))
|
||||||
|
goto exception;
|
||||||
|
for (;;) {
|
||||||
|
item = JS_IteratorNext(ctx, iter, next, 0, NULL, &done);
|
||||||
|
if (JS_IsException(item))
|
||||||
|
goto exception;
|
||||||
|
if (done) // item is JS_UNDEFINED
|
||||||
|
break;
|
||||||
|
// note the subtlety here: due to mutating iterators, it's
|
||||||
|
// possible for keys to disappear during iteration; test262
|
||||||
|
// still expects us to maintain insertion order though, so
|
||||||
|
// we first check |this|, then |new|; |new| is a copy of |this|
|
||||||
|
// - if item exists in |this|, delete (if it exists) from |new|
|
||||||
|
// - if item misses in |this| and |new|, add to |new|
|
||||||
|
// - if item exists in |new| but misses in |this|, *don't* add it,
|
||||||
|
// mutating iterator erased it
|
||||||
|
item = map_normalize_key(ctx, item);
|
||||||
|
present = (NULL != map_find_record(ctx, s, item));
|
||||||
|
mr = map_find_record(ctx, t, item);
|
||||||
|
if (present) {
|
||||||
|
if (mr)
|
||||||
|
map_delete_record(ctx->rt, t, mr);
|
||||||
|
JS_FreeValue(ctx, item);
|
||||||
|
} else if (mr) {
|
||||||
|
JS_FreeValue(ctx, item);
|
||||||
|
} else {
|
||||||
|
mr = map_add_record(ctx, t, item);
|
||||||
|
if (!mr) {
|
||||||
|
JS_FreeValue(ctx, item);
|
||||||
|
goto exception;
|
||||||
|
}
|
||||||
|
mr->value = JS_UNDEFINED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
goto fini;
|
||||||
|
exception:
|
||||||
|
JS_FreeValue(ctx, newset);
|
||||||
|
newset = JS_EXCEPTION;
|
||||||
|
fini:
|
||||||
|
JS_FreeValue(ctx, next);
|
||||||
|
JS_FreeValue(ctx, iter);
|
||||||
|
return newset;
|
||||||
|
}
|
||||||
|
|
||||||
static JSValue js_set_union(JSContext *ctx, JSValue this_val,
|
static JSValue js_set_union(JSContext *ctx, JSValue this_val,
|
||||||
int argc, JSValue *argv)
|
int argc, JSValue *argv)
|
||||||
{
|
{
|
||||||
JSValue newset, item, iter, next, rv;
|
JSValue newset, item, iter, next, rv;
|
||||||
struct list_head *el;
|
struct list_head *el;
|
||||||
|
JSMapState *s, *t;
|
||||||
JSMapRecord *mr;
|
JSMapRecord *mr;
|
||||||
JSMapState *s;
|
|
||||||
int64_t size;
|
int64_t size;
|
||||||
BOOL done;
|
BOOL done;
|
||||||
|
|
||||||
|
@ -46349,16 +46436,17 @@ static JSValue js_set_union(JSContext *ctx, JSValue this_val,
|
||||||
newset = js_map_constructor(ctx, JS_UNDEFINED, 0, NULL, MAGIC_SET);
|
newset = js_map_constructor(ctx, JS_UNDEFINED, 0, NULL, MAGIC_SET);
|
||||||
if (JS_IsException(newset))
|
if (JS_IsException(newset))
|
||||||
return JS_EXCEPTION;
|
return JS_EXCEPTION;
|
||||||
|
t = JS_GetOpaque(newset, JS_CLASS_SET);
|
||||||
iter = JS_UNDEFINED;
|
iter = JS_UNDEFINED;
|
||||||
next = JS_UNDEFINED;
|
next = JS_UNDEFINED;
|
||||||
list_for_each(el, &s->records) {
|
list_for_each(el, &s->records) {
|
||||||
mr = list_entry(el, JSMapRecord, link);
|
mr = list_entry(el, JSMapRecord, link);
|
||||||
if (mr->empty)
|
if (mr->empty)
|
||||||
continue;
|
continue;
|
||||||
rv = js_map_set(ctx, newset, 1, &mr->key, MAGIC_SET);
|
mr = map_add_record(ctx, t, js_dup(mr->key));
|
||||||
if (JS_IsException(rv))
|
if (!mr)
|
||||||
goto exception;
|
goto exception;
|
||||||
JS_FreeValue(ctx, rv);
|
mr->value = JS_UNDEFINED;
|
||||||
}
|
}
|
||||||
iter = JS_GetProperty(ctx, argv[0], JS_ATOM_keys);
|
iter = JS_GetProperty(ctx, argv[0], JS_ATOM_keys);
|
||||||
if (JS_IsException(iter))
|
if (JS_IsException(iter))
|
||||||
|
@ -46424,6 +46512,7 @@ static const JSCFunctionListEntry js_set_proto_funcs[] = {
|
||||||
JS_CGETSET_MAGIC_DEF("size", js_map_get_size, NULL, MAGIC_SET ),
|
JS_CGETSET_MAGIC_DEF("size", js_map_get_size, NULL, MAGIC_SET ),
|
||||||
JS_CFUNC_MAGIC_DEF("forEach", 1, js_map_forEach, MAGIC_SET ),
|
JS_CFUNC_MAGIC_DEF("forEach", 1, js_map_forEach, MAGIC_SET ),
|
||||||
JS_CFUNC_DEF("difference", 1, js_set_difference ),
|
JS_CFUNC_DEF("difference", 1, js_set_difference ),
|
||||||
|
JS_CFUNC_DEF("symmetricDifference", 1, js_set_symmetricDifference ),
|
||||||
JS_CFUNC_DEF("union", 1, js_set_union ),
|
JS_CFUNC_DEF("union", 1, js_set_union ),
|
||||||
JS_CFUNC_MAGIC_DEF("values", 0, js_create_map_iterator, (JS_ITERATOR_KIND_KEY << 2) | MAGIC_SET ),
|
JS_CFUNC_MAGIC_DEF("values", 0, js_create_map_iterator, (JS_ITERATOR_KIND_KEY << 2) | MAGIC_SET ),
|
||||||
JS_ALIAS_DEF("keys", "values" ),
|
JS_ALIAS_DEF("keys", "values" ),
|
||||||
|
|
|
@ -230,52 +230,6 @@ test262/test/built-ins/Set/prototype/isSupersetOf/size-is-a-number.js:24: Test26
|
||||||
test262/test/built-ins/Set/prototype/isSupersetOf/size-is-a-number.js:24: strict mode: Test262Error: GetSetRecord coerces size Expected SameValue(«0», «1») to be true
|
test262/test/built-ins/Set/prototype/isSupersetOf/size-is-a-number.js:24: strict mode: Test262Error: GetSetRecord coerces size Expected SameValue(«0», «1») to be true
|
||||||
test262/test/built-ins/Set/prototype/isSupersetOf/subclass-receiver-methods.js:32: TypeError: not a function
|
test262/test/built-ins/Set/prototype/isSupersetOf/subclass-receiver-methods.js:32: TypeError: not a function
|
||||||
test262/test/built-ins/Set/prototype/isSupersetOf/subclass-receiver-methods.js:32: strict mode: TypeError: not a function
|
test262/test/built-ins/Set/prototype/isSupersetOf/subclass-receiver-methods.js:32: strict mode: TypeError: not a function
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/add-not-called.js:21: TypeError: not a function
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/add-not-called.js:21: strict mode: TypeError: not a function
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/allows-set-like-class.js:31: TypeError: not a function
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/allows-set-like-class.js:31: strict mode: TypeError: not a function
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/allows-set-like-object.js:29: TypeError: not a function
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/allows-set-like-object.js:29: strict mode: TypeError: not a function
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/builtins.js:9: Test262Error: Built-in objects must be extensible. Expected SameValue(«false», «true») to be true
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/builtins.js:9: strict mode: Test262Error: Built-in objects must be extensible. Expected SameValue(«false», «true») to be true
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/combines-Map.js:16: TypeError: not a function
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/combines-Map.js:16: strict mode: TypeError: not a function
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/combines-empty-sets.js:13: TypeError: not a function
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/combines-empty-sets.js:13: strict mode: TypeError: not a function
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/combines-itself.js:12: TypeError: not a function
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/combines-itself.js:12: strict mode: TypeError: not a function
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/combines-same-sets.js:13: TypeError: not a function
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/combines-same-sets.js:13: strict mode: TypeError: not a function
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/combines-sets.js:13: TypeError: not a function
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/combines-sets.js:13: strict mode: TypeError: not a function
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/converts-negative-zero.js:25: TypeError: not a function
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/converts-negative-zero.js:25: strict mode: TypeError: not a function
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/length.js:11: Test262Error: Expected SameValue(«undefined», «function») to be true
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/length.js:11: strict mode: Test262Error: Expected SameValue(«undefined», «function») to be true
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/name.js:11: Test262Error: Expected SameValue(«undefined», «function») to be true
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/name.js:11: strict mode: Test262Error: Expected SameValue(«undefined», «function») to be true
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/not-a-constructor.js:17: Test262Error: isConstructor invoked with a non-function value
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/not-a-constructor.js:17: strict mode: Test262Error: isConstructor invoked with a non-function value
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/require-internal-slot.js:17: Test262Error: Expected SameValue(«undefined», «function») to be true
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/require-internal-slot.js:17: strict mode: Test262Error: Expected SameValue(«undefined», «function») to be true
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/result-order.js:15: TypeError: not a function
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/result-order.js:15: strict mode: TypeError: not a function
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/set-like-array.js:21: TypeError: not a function
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/set-like-array.js:21: strict mode: TypeError: not a function
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/set-like-class-mutation.js:44: TypeError: not a function
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/set-like-class-mutation.js:44: strict mode: TypeError: not a function
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/set-like-class-order.js:66: TypeError: not a function
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/set-like-class-order.js:66: strict mode: TypeError: not a function
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/size-is-a-number.js:24: Test262Error: GetSetRecord coerces size Expected SameValue(«0», «1») to be true
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/size-is-a-number.js:24: strict mode: Test262Error: GetSetRecord coerces size Expected SameValue(«0», «1») to be true
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/subclass-receiver-methods.js:34: TypeError: not a function
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/subclass-receiver-methods.js:34: strict mode: TypeError: not a function
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/subclass-symbol-species.js:20: TypeError: not a function
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/subclass-symbol-species.js:20: strict mode: TypeError: not a function
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/subclass.js:15: TypeError: not a function
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/subclass.js:15: strict mode: TypeError: not a function
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/symmetricDifference.js:10: Test262Error: `typeof Set.prototype.symmetricDifference` is `'function'` Expected SameValue(«undefined», «function») to be true
|
|
||||||
test262/test/built-ins/Set/prototype/symmetricDifference/symmetricDifference.js:10: strict mode: Test262Error: `typeof Set.prototype.symmetricDifference` is `'function'` Expected SameValue(«undefined», «function») to be true
|
|
||||||
test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-canonical-invalid-index-prototype-chain-set.js:35: Test262Error: value should not be coerced Expected SameValue(«22», «0») to be true
|
test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-canonical-invalid-index-prototype-chain-set.js:35: Test262Error: value should not be coerced Expected SameValue(«22», «0») to be true
|
||||||
test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-canonical-invalid-index-prototype-chain-set.js:35: strict mode: Test262Error: value should not be coerced Expected SameValue(«22», «0») to be true
|
test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-canonical-invalid-index-prototype-chain-set.js:35: strict mode: Test262Error: value should not be coerced Expected SameValue(«22», «0») to be true
|
||||||
test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-canonical-invalid-index-reflect-set.js:35: Test262Error: value should not be coerced Expected SameValue(«32», «0») to be true
|
test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-canonical-invalid-index-reflect-set.js:35: Test262Error: value should not be coerced Expected SameValue(«32», «0») to be true
|
||||||
|
|
Loading…
Reference in a new issue