Skip to content

Commit b751ed5

Browse files
authored
Add Set.prototype.intersection (#511)
1 parent 6ba2448 commit b751ed5

File tree

2 files changed

+116
-61
lines changed

2 files changed

+116
-61
lines changed

quickjs.c

Lines changed: 116 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46241,6 +46241,105 @@ static int js_setlike_get_keys(JSContext *ctx, JSValue setlike, JSValue *pout)
4624146241
return 0;
4624246242
}
4624346243

46244+
static JSValue js_set_intersection(JSContext *ctx, JSValue this_val,
46245+
int argc, JSValue *argv)
46246+
{
46247+
JSValue newset, item, iter, keys, has, next, rv;
46248+
JSMapState *s, *t;
46249+
JSMapRecord *mr;
46250+
int64_t size;
46251+
BOOL done;
46252+
int ok;
46253+
46254+
has = JS_UNDEFINED;
46255+
iter = JS_UNDEFINED;
46256+
keys = JS_UNDEFINED;
46257+
next = JS_UNDEFINED;
46258+
newset = JS_UNDEFINED;
46259+
s = JS_GetOpaque2(ctx, this_val, JS_CLASS_SET);
46260+
if (!s)
46261+
goto exception;
46262+
// order matters!
46263+
if (js_setlike_get_size(ctx, argv[0], &size) < 0)
46264+
goto exception;
46265+
if (js_setlike_get_has(ctx, argv[0], &has) < 0)
46266+
goto exception;
46267+
if (js_setlike_get_keys(ctx, argv[0], &keys) < 0)
46268+
goto exception;
46269+
if (s->record_count > size) {
46270+
iter = JS_Call(ctx, keys, argv[0], 0, NULL);
46271+
if (JS_IsException(iter))
46272+
goto exception;
46273+
next = JS_GetProperty(ctx, iter, JS_ATOM_next);
46274+
if (JS_IsException(next))
46275+
goto exception;
46276+
newset = js_map_constructor(ctx, JS_UNDEFINED, 0, NULL, MAGIC_SET);
46277+
if (JS_IsException(newset))
46278+
goto exception;
46279+
t = JS_GetOpaque(newset, JS_CLASS_SET);
46280+
for (;;) {
46281+
item = JS_IteratorNext(ctx, iter, next, 0, NULL, &done);
46282+
if (JS_IsException(item))
46283+
goto exception;
46284+
if (done) // item is JS_UNDEFINED
46285+
break;
46286+
item = map_normalize_key(ctx, item);
46287+
if (!map_find_record(ctx, s, item)) {
46288+
JS_FreeValue(ctx, item);
46289+
} else if (map_find_record(ctx, t, item)) {
46290+
JS_FreeValue(ctx, item); // no duplicates
46291+
} else if ((mr = map_add_record(ctx, t, item))) {
46292+
mr->value = JS_UNDEFINED;
46293+
} else {
46294+
JS_FreeValue(ctx, item);
46295+
goto exception;
46296+
}
46297+
}
46298+
} else {
46299+
iter = js_create_map_iterator(ctx, this_val, 0, NULL, MAGIC_SET);
46300+
if (JS_IsException(iter))
46301+
goto exception;
46302+
newset = js_map_constructor(ctx, JS_UNDEFINED, 0, NULL, MAGIC_SET);
46303+
if (JS_IsException(newset))
46304+
goto exception;
46305+
t = JS_GetOpaque(newset, JS_CLASS_SET);
46306+
for (;;) {
46307+
item = js_map_iterator_next(ctx, iter, 0, NULL, &done, MAGIC_SET);
46308+
if (JS_IsException(item))
46309+
goto exception;
46310+
if (done) // item is JS_UNDEFINED
46311+
break;
46312+
rv = JS_Call(ctx, has, argv[0], 1, &item);
46313+
ok = JS_ToBoolFree(ctx, rv); // returns -1 if rv is JS_EXCEPTION
46314+
if (ok > 0) {
46315+
item = map_normalize_key(ctx, item);
46316+
if (map_find_record(ctx, t, item)) {
46317+
JS_FreeValue(ctx, item); // no duplicates
46318+
} else if ((mr = map_add_record(ctx, t, item))) {
46319+
mr->value = JS_UNDEFINED;
46320+
} else {
46321+
JS_FreeValue(ctx, item);
46322+
goto exception;
46323+
}
46324+
} else {
46325+
JS_FreeValue(ctx, item);
46326+
if (ok < 0)
46327+
goto exception;
46328+
}
46329+
}
46330+
}
46331+
goto fini;
46332+
exception:
46333+
JS_FreeValue(ctx, newset);
46334+
newset = JS_EXCEPTION;
46335+
fini:
46336+
JS_FreeValue(ctx, has);
46337+
JS_FreeValue(ctx, keys);
46338+
JS_FreeValue(ctx, iter);
46339+
JS_FreeValue(ctx, next);
46340+
return newset;
46341+
}
46342+
4624446343
static JSValue js_set_difference(JSContext *ctx, JSValue this_val,
4624546344
int argc, JSValue *argv)
4624646345
{
@@ -46296,6 +46395,7 @@ static JSValue js_set_difference(JSContext *ctx, JSValue this_val,
4629646395
newset = js_map_constructor(ctx, JS_UNDEFINED, 0, NULL, MAGIC_SET);
4629746396
if (JS_IsException(newset))
4629846397
goto exception;
46398+
t = JS_GetOpaque(newset, JS_CLASS_SET);
4629946399
for (;;) {
4630046400
item = js_map_iterator_next(ctx, iter, 0, NULL, &done, MAGIC_SET);
4630146401
if (JS_IsException(item))
@@ -46304,15 +46404,21 @@ static JSValue js_set_difference(JSContext *ctx, JSValue this_val,
4630446404
break;
4630546405
rv = JS_Call(ctx, has, argv[0], 1, &item);
4630646406
ok = JS_ToBoolFree(ctx, rv); // returns -1 if rv is JS_EXCEPTION
46307-
rv = JS_UNDEFINED;
46308-
if (ok == 0)
46309-
rv = js_map_set(ctx, newset, 1, &item, MAGIC_SET);
46310-
JS_FreeValue(ctx, item);
46311-
if (JS_IsException(rv))
46312-
goto exception;
46313-
JS_FreeValue(ctx, rv);
46314-
if (ok < 0)
46315-
goto exception;
46407+
if (ok == 0) {
46408+
item = map_normalize_key(ctx, item);
46409+
if (map_find_record(ctx, t, item)) {
46410+
JS_FreeValue(ctx, item); // no duplicates
46411+
} else if ((mr = map_add_record(ctx, t, item))) {
46412+
mr->value = JS_UNDEFINED;
46413+
} else {
46414+
JS_FreeValue(ctx, item);
46415+
goto exception;
46416+
}
46417+
} else {
46418+
JS_FreeValue(ctx, item);
46419+
if (ok < 0)
46420+
goto exception;
46421+
}
4631646422
}
4631746423
}
4631846424
goto fini;
@@ -46511,6 +46617,7 @@ static const JSCFunctionListEntry js_set_proto_funcs[] = {
4651146617
JS_CFUNC_MAGIC_DEF("clear", 0, js_map_clear, MAGIC_SET ),
4651246618
JS_CGETSET_MAGIC_DEF("size", js_map_get_size, NULL, MAGIC_SET ),
4651346619
JS_CFUNC_MAGIC_DEF("forEach", 1, js_map_forEach, MAGIC_SET ),
46620+
JS_CFUNC_DEF("intersection", 1, js_set_intersection ),
4651446621
JS_CFUNC_DEF("difference", 1, js_set_difference ),
4651546622
JS_CFUNC_DEF("symmetricDifference", 1, js_set_symmetricDifference ),
4651646623
JS_CFUNC_DEF("union", 1, js_set_union ),

test262_errors.txt

Lines changed: 0 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -72,52 +72,6 @@ test262/test/built-ins/RegExp/property-escapes/generated/XID_Start.js:16: Test26
7272
test262/test/built-ins/RegExp/property-escapes/generated/XID_Start.js:16: strict mode: Test262Error: `\p{XID_Start}` should match U+02EBF0 (`𮯰`)
7373
test262/test/built-ins/RegExp/unicode_full_case_folding.js:20: Test262Error: \u0390 does not match \u1fd3
7474
test262/test/built-ins/RegExp/unicode_full_case_folding.js:20: strict mode: Test262Error: \u0390 does not match \u1fd3
75-
test262/test/built-ins/Set/prototype/intersection/add-not-called.js:21: TypeError: not a function
76-
test262/test/built-ins/Set/prototype/intersection/add-not-called.js:21: strict mode: TypeError: not a function
77-
test262/test/built-ins/Set/prototype/intersection/allows-set-like-class.js:32: TypeError: not a function
78-
test262/test/built-ins/Set/prototype/intersection/allows-set-like-class.js:32: strict mode: TypeError: not a function
79-
test262/test/built-ins/Set/prototype/intersection/allows-set-like-object.js:30: TypeError: not a function
80-
test262/test/built-ins/Set/prototype/intersection/allows-set-like-object.js:30: strict mode: TypeError: not a function
81-
test262/test/built-ins/Set/prototype/intersection/builtins.js:9: Test262Error: Built-in objects must be extensible. Expected SameValue(«false», «true») to be true
82-
test262/test/built-ins/Set/prototype/intersection/builtins.js:9: strict mode: Test262Error: Built-in objects must be extensible. Expected SameValue(«false», «true») to be true
83-
test262/test/built-ins/Set/prototype/intersection/combines-Map.js:16: TypeError: not a function
84-
test262/test/built-ins/Set/prototype/intersection/combines-Map.js:16: strict mode: TypeError: not a function
85-
test262/test/built-ins/Set/prototype/intersection/combines-empty-sets.js:13: TypeError: not a function
86-
test262/test/built-ins/Set/prototype/intersection/combines-empty-sets.js:13: strict mode: TypeError: not a function
87-
test262/test/built-ins/Set/prototype/intersection/combines-itself.js:12: TypeError: not a function
88-
test262/test/built-ins/Set/prototype/intersection/combines-itself.js:12: strict mode: TypeError: not a function
89-
test262/test/built-ins/Set/prototype/intersection/combines-same-sets.js:13: TypeError: not a function
90-
test262/test/built-ins/Set/prototype/intersection/combines-same-sets.js:13: strict mode: TypeError: not a function
91-
test262/test/built-ins/Set/prototype/intersection/combines-sets.js:13: TypeError: not a function
92-
test262/test/built-ins/Set/prototype/intersection/combines-sets.js:13: strict mode: TypeError: not a function
93-
test262/test/built-ins/Set/prototype/intersection/converts-negative-zero.js:25: TypeError: not a function
94-
test262/test/built-ins/Set/prototype/intersection/converts-negative-zero.js:25: strict mode: TypeError: not a function
95-
test262/test/built-ins/Set/prototype/intersection/intersection.js:10: Test262Error: `typeof Set.prototype.intersection` is `'function'` Expected SameValue(«undefined», «function») to be true
96-
test262/test/built-ins/Set/prototype/intersection/intersection.js:10: strict mode: Test262Error: `typeof Set.prototype.intersection` is `'function'` Expected SameValue(«undefined», «function») to be true
97-
test262/test/built-ins/Set/prototype/intersection/length.js:11: Test262Error: Expected SameValue(«undefined», «function») to be true
98-
test262/test/built-ins/Set/prototype/intersection/length.js:11: strict mode: Test262Error: Expected SameValue(«undefined», «function») to be true
99-
test262/test/built-ins/Set/prototype/intersection/name.js:11: Test262Error: Expected SameValue(«undefined», «function») to be true
100-
test262/test/built-ins/Set/prototype/intersection/name.js:11: strict mode: Test262Error: Expected SameValue(«undefined», «function») to be true
101-
test262/test/built-ins/Set/prototype/intersection/not-a-constructor.js:17: Test262Error: isConstructor invoked with a non-function value
102-
test262/test/built-ins/Set/prototype/intersection/not-a-constructor.js:17: strict mode: Test262Error: isConstructor invoked with a non-function value
103-
test262/test/built-ins/Set/prototype/intersection/require-internal-slot.js:17: Test262Error: Expected SameValue(«undefined», «function») to be true
104-
test262/test/built-ins/Set/prototype/intersection/require-internal-slot.js:17: strict mode: Test262Error: Expected SameValue(«undefined», «function») to be true
105-
test262/test/built-ins/Set/prototype/intersection/result-order.js:15: TypeError: not a function
106-
test262/test/built-ins/Set/prototype/intersection/result-order.js:15: strict mode: TypeError: not a function
107-
test262/test/built-ins/Set/prototype/intersection/set-like-array.js:23: TypeError: not a function
108-
test262/test/built-ins/Set/prototype/intersection/set-like-array.js:23: strict mode: TypeError: not a function
109-
test262/test/built-ins/Set/prototype/intersection/set-like-class-mutation.js:44: TypeError: not a function
110-
test262/test/built-ins/Set/prototype/intersection/set-like-class-mutation.js:44: strict mode: TypeError: not a function
111-
test262/test/built-ins/Set/prototype/intersection/set-like-class-order.js:67: TypeError: not a function
112-
test262/test/built-ins/Set/prototype/intersection/set-like-class-order.js:67: strict mode: TypeError: not a function
113-
test262/test/built-ins/Set/prototype/intersection/size-is-a-number.js:24: Test262Error: GetSetRecord coerces size Expected SameValue(«0», «1») to be true
114-
test262/test/built-ins/Set/prototype/intersection/size-is-a-number.js:24: strict mode: Test262Error: GetSetRecord coerces size Expected SameValue(«0», «1») to be true
115-
test262/test/built-ins/Set/prototype/intersection/subclass-receiver-methods.js:34: TypeError: not a function
116-
test262/test/built-ins/Set/prototype/intersection/subclass-receiver-methods.js:34: strict mode: TypeError: not a function
117-
test262/test/built-ins/Set/prototype/intersection/subclass-symbol-species.js:20: TypeError: not a function
118-
test262/test/built-ins/Set/prototype/intersection/subclass-symbol-species.js:20: strict mode: TypeError: not a function
119-
test262/test/built-ins/Set/prototype/intersection/subclass.js:15: TypeError: not a function
120-
test262/test/built-ins/Set/prototype/intersection/subclass.js:15: strict mode: TypeError: not a function
12175
test262/test/built-ins/Set/prototype/isDisjointFrom/allows-set-like-class.js:30: TypeError: not a function
12276
test262/test/built-ins/Set/prototype/isDisjointFrom/allows-set-like-class.js:30: strict mode: TypeError: not a function
12377
test262/test/built-ins/Set/prototype/isDisjointFrom/allows-set-like-object.js:28: TypeError: not a function
@@ -263,10 +217,4 @@ test262/test/staging/set-is-subset-table-receiver-cleared.js:25: TypeError: not
263217
test262/test/staging/set-is-subset-table-receiver-cleared.js:25: strict mode: TypeError: not a function
264218
test262/test/staging/set-is-subset-table-transition.js:28: TypeError: not a function
265219
test262/test/staging/set-is-subset-table-transition.js:28: strict mode: TypeError: not a function
266-
test262/test/staging/set-methods/set-intersect-other-is-set-like.js:29: TypeError: not a function
267-
test262/test/staging/set-methods/set-intersect-other-is-set-like.js:29: strict mode: TypeError: not a function
268-
test262/test/staging/set-methods/set-intersection-other-is-map.js:22: TypeError: not a function
269-
test262/test/staging/set-methods/set-intersection-other-is-map.js:22: strict mode: TypeError: not a function
270-
test262/test/staging/set-methods/set-intersection-other-is-set.js:22: TypeError: not a function
271-
test262/test/staging/set-methods/set-intersection-other-is-set.js:22: strict mode: TypeError: not a function
272220
test262/test/staging/top-level-await/tla-hang-entry.js:10: TypeError: $DONE() not called

0 commit comments

Comments
 (0)