Skip to content

Commit 6167dcb

Browse files
authored
Call return() method of Set-like iterators (#1167)
Change the behavior of the following methods: - Set.prototype.isDisjointFrom - Set.prototype.isSupersetOf Specifically, for iterators coming from set-like objects: - DO NOT invoke return() when the iterator is exhausted - DO invoke return() when the iterator is NOT exhausted test262 doesn't test it but the spec seems to mandate it and V8 and SM both implement it.
1 parent e627e37 commit 6167dcb

File tree

2 files changed

+57
-4
lines changed

2 files changed

+57
-4
lines changed

quickjs.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49450,7 +49450,7 @@ static JSValue js_set_isDisjointFrom(JSContext *ctx, JSValueConst this_val,
4945049450
if (JS_IsException(next))
4945149451
goto exception;
4945249452
found = false;
49453-
do {
49453+
for (;;) {
4945449454
item = JS_IteratorNext(ctx, iter, next, 0, NULL, &done);
4945549455
if (JS_IsException(item))
4945649456
goto exception;
@@ -49459,7 +49459,12 @@ static JSValue js_set_isDisjointFrom(JSContext *ctx, JSValueConst this_val,
4945949459
item = map_normalize_key(ctx, item);
4946049460
found = (NULL != map_find_record(ctx, s, item));
4946149461
JS_FreeValue(ctx, item);
49462-
} while (!found);
49462+
if (!found)
49463+
continue;
49464+
if (JS_IteratorClose(ctx, iter, /*is_exception_pending*/false) < 0)
49465+
goto exception;
49466+
break;
49467+
}
4946349468
} else {
4946449469
iter = js_create_map_iterator(ctx, this_val, 0, NULL, MAGIC_SET);
4946549470
if (JS_IsException(iter))
@@ -49576,7 +49581,7 @@ static JSValue js_set_isSupersetOf(JSContext *ctx, JSValueConst this_val,
4957649581
if (JS_IsException(next))
4957749582
goto exception;
4957849583
found = true;
49579-
do {
49584+
for (;;) {
4958049585
item = JS_IteratorNext(ctx, iter, next, 0, NULL, &done);
4958149586
if (JS_IsException(item))
4958249587
goto exception;
@@ -49585,7 +49590,12 @@ static JSValue js_set_isSupersetOf(JSContext *ctx, JSValueConst this_val,
4958549590
item = map_normalize_key(ctx, item);
4958649591
found = (NULL != map_find_record(ctx, s, item));
4958749592
JS_FreeValue(ctx, item);
49588-
} while (found);
49593+
if (found)
49594+
continue;
49595+
if (JS_IteratorClose(ctx, iter, /*is_exception_pending*/false) < 0)
49596+
goto exception;
49597+
break;
49598+
}
4958949599
fini:
4959049600
rval = found ? JS_TRUE : JS_FALSE;
4959149601
exception:

tests/test_builtin.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -908,6 +908,48 @@ function test_weak_map()
908908
/* the WeakMap should be empty here */
909909
}
910910

911+
function test_set()
912+
{
913+
const iter = {
914+
a: [4, 5, 6],
915+
nextCalls: 0,
916+
returnCalls: 0,
917+
next() {
918+
const done = this.nextCalls >= this.a.length
919+
const value = this.a[this.nextCalls]
920+
this.nextCalls++
921+
return {done, value}
922+
},
923+
return() {
924+
this.returnCalls++
925+
return this
926+
},
927+
}
928+
const setlike = {
929+
size: iter.a.length,
930+
has(v) { return iter.a.includes(v) },
931+
keys() { return iter },
932+
}
933+
// set must be bigger than iter.a to hit iter.next and iter.return
934+
assert(new Set([4,5,6,7]).isSupersetOf(setlike), true)
935+
assert(iter.nextCalls, 4);
936+
assert(iter.returnCalls, 0);
937+
iter.nextCalls = iter.returnCalls = 0
938+
assert(new Set([0,1,2,3]).isSupersetOf(setlike), false)
939+
assert(iter.nextCalls, 1);
940+
assert(iter.returnCalls, 1);
941+
iter.nextCalls = iter.returnCalls = 0
942+
// set must be bigger than iter.a to hit iter.next and iter.return
943+
assert(new Set([4,5,6,7]).isDisjointFrom(setlike), false)
944+
assert(iter.nextCalls, 1);
945+
assert(iter.returnCalls, 1);
946+
iter.nextCalls = iter.returnCalls = 0
947+
assert(new Set([0,1,2,3]).isDisjointFrom(setlike), true)
948+
assert(iter.nextCalls, 4);
949+
assert(iter.returnCalls, 0);
950+
iter.nextCalls = iter.returnCalls = 0
951+
}
952+
911953
function test_weak_set()
912954
{
913955
var a, e;
@@ -1103,6 +1145,7 @@ test_regexp();
11031145
test_symbol();
11041146
test_map();
11051147
test_weak_map();
1148+
test_set();
11061149
test_weak_set();
11071150
test_generator();
11081151
test_proxy_iter();

0 commit comments

Comments
 (0)