Skip to content

Commit abf571a

Browse files
author
Fabrice Bellard
committed
fixed 'return' invocation in Iterator helpers - fixed 'next' method get in Iterator.prototype.flatMap (#539)
1 parent 22f8302 commit abf571a

1 file changed

Lines changed: 114 additions & 150 deletions

File tree

‎quickjs.c‎

Lines changed: 114 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -44200,6 +44200,7 @@ typedef struct JSIteratorHelperData {
4420044200
JSValue next;
4420144201
JSValue func; // predicate (filter) or mapper (flatMap, map)
4420244202
JSValue inner; // innerValue (flatMap)
44203+
JSValue inner_next; // innerValue next method (flatMap)
4420344204
int64_t count; // limit (drop, take) or counter (filter, map, flatMap)
4420444205
JSIteratorHelperKindEnum kind : 8;
4420544206
uint8_t executing : 1;
@@ -44271,6 +44272,7 @@ static JSValue js_create_iterator_helper(JSContext *ctx, JSValueConst this_val,
4427144272
it->func = JS_DupValue(ctx, func);
4427244273
it->next = method;
4427344274
it->inner = JS_UNDEFINED;
44275+
it->inner_next = JS_UNDEFINED;
4427444276
it->count = count;
4427544277
it->executing = 0;
4427644278
it->done = 0;
@@ -44582,6 +44584,7 @@ static void js_iterator_helper_finalizer(JSRuntime *rt, JSValue val)
4458244584
JS_FreeValueRT(rt, it->func);
4458344585
JS_FreeValueRT(rt, it->next);
4458444586
JS_FreeValueRT(rt, it->inner);
44587+
JS_FreeValueRT(rt, it->inner_next);
4458544588
js_free_rt(rt, it);
4458644589
}
4458744590
}
@@ -44596,6 +44599,7 @@ static void js_iterator_helper_mark(JSRuntime *rt, JSValueConst val,
4459644599
JS_MarkValue(rt, it->func, mark_func);
4459744600
JS_MarkValue(rt, it->next, mark_func);
4459844601
JS_MarkValue(rt, it->inner, mark_func);
44602+
JS_MarkValue(rt, it->inner_next, mark_func);
4459944603
}
4460044604
}
4460144605

@@ -44620,183 +44624,154 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val,
4462044624

4462144625
it->executing = 1;
4462244626

44627+
if (magic == GEN_MAGIC_RETURN) {
44628+
*pdone = TRUE;
44629+
ret = JS_UNDEFINED;
44630+
44631+
if (!JS_IsUndefined(it->inner)) {
44632+
if (JS_IteratorClose(ctx, it->inner, FALSE))
44633+
ret = JS_EXCEPTION;
44634+
JS_FreeValue(ctx, it->inner);
44635+
JS_FreeValue(ctx, it->inner_next);
44636+
it->inner = JS_UNDEFINED;
44637+
it->inner_next = JS_UNDEFINED;
44638+
}
44639+
if (JS_IteratorClose(ctx, it->obj, JS_IsException(ret)))
44640+
ret = JS_EXCEPTION;
44641+
goto done;
44642+
}
44643+
4462344644
switch (it->kind) {
4462444645
case JS_ITERATOR_HELPER_KIND_DROP:
4462544646
{
44626-
JSValue item, method;
44627-
if (magic == GEN_MAGIC_NEXT) {
44628-
method = JS_DupValue(ctx, it->next);
44629-
} else {
44630-
method = JS_GetProperty(ctx, it->obj, JS_ATOM_return);
44631-
if (JS_IsException(method))
44632-
goto fail;
44633-
}
44647+
JSValue item;
4463444648
while (it->count > 0) {
4463544649
it->count--;
44636-
item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone);
44637-
if (JS_IsException(item)) {
44638-
JS_FreeValue(ctx, method);
44650+
item = JS_IteratorNext(ctx, it->obj, it->next, 0, NULL, pdone);
44651+
if (JS_IsException(item))
4463944652
goto fail_no_close;
44640-
}
4464144653
JS_FreeValue(ctx, item);
44642-
if (magic == GEN_MAGIC_RETURN)
44643-
*pdone = TRUE;
4464444654
if (*pdone) {
44645-
JS_FreeValue(ctx, method);
4464644655
ret = JS_UNDEFINED;
4464744656
goto done;
4464844657
}
4464944658
}
4465044659

44651-
item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone);
44652-
JS_FreeValue(ctx, method);
44660+
item = JS_IteratorNext(ctx, it->obj, it->next, 0, NULL, pdone);
4465344661
if (JS_IsException(item))
4465444662
goto fail_no_close;
4465544663
ret = item;
44656-
goto done;
4465744664
}
4465844665
break;
4465944666
case JS_ITERATOR_HELPER_KIND_FILTER:
4466044667
{
44661-
JSValue item, method, selected, index_val;
44668+
JSValue item, selected, index_val;
4466244669
JSValueConst args[2];
44663-
if (magic == GEN_MAGIC_NEXT) {
44664-
method = JS_DupValue(ctx, it->next);
44665-
} else {
44666-
method = JS_GetProperty(ctx, it->obj, JS_ATOM_return);
44667-
if (JS_IsException(method))
44668-
goto fail;
44669-
}
44670-
filter_again:
44671-
item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone);
44672-
if (JS_IsException(item)) {
44673-
JS_FreeValue(ctx, method);
44674-
goto fail_no_close;
44675-
}
44676-
if (*pdone || magic == GEN_MAGIC_RETURN) {
44677-
JS_FreeValue(ctx, method);
44678-
ret = item;
44679-
goto done;
44680-
}
44681-
index_val = JS_NewInt64(ctx, it->count++);
44682-
args[0] = item;
44683-
args[1] = index_val;
44684-
selected = JS_Call(ctx, it->func, JS_UNDEFINED, countof(args), args);
44685-
JS_FreeValue(ctx, index_val);
44686-
if (JS_IsException(selected)) {
44687-
JS_FreeValue(ctx, item);
44688-
JS_FreeValue(ctx, method);
44689-
goto fail;
44690-
}
44691-
if (JS_ToBoolFree(ctx, selected)) {
44692-
JS_FreeValue(ctx, method);
44693-
ret = item;
44694-
goto done;
44695-
}
44696-
JS_FreeValue(ctx, item);
44697-
goto filter_again;
44698-
}
44699-
break;
44700-
case JS_ITERATOR_HELPER_KIND_FLAT_MAP:
44701-
{
44702-
JSValue item, method, index_val, iter;
44703-
JSValueConst args[2];
44704-
flat_map_again:
44705-
if (JS_IsUndefined(it->inner)) {
44706-
if (magic == GEN_MAGIC_NEXT) {
44707-
method = JS_DupValue(ctx, it->next);
44708-
} else {
44709-
method = JS_GetProperty(ctx, it->obj, JS_ATOM_return);
44710-
if (JS_IsException(method))
44711-
goto fail;
44712-
}
44713-
item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone);
44714-
JS_FreeValue(ctx, method);
44670+
for(;;) {
44671+
item = JS_IteratorNext(ctx, it->obj, it->next, 0, NULL, pdone);
4471544672
if (JS_IsException(item))
4471644673
goto fail_no_close;
44717-
if (*pdone || magic == GEN_MAGIC_RETURN) {
44674+
if (*pdone) {
4471844675
ret = item;
44719-
goto done;
44676+
break;
4472044677
}
4472144678
index_val = JS_NewInt64(ctx, it->count++);
4472244679
args[0] = item;
4472344680
args[1] = index_val;
44724-
ret = JS_Call(ctx, it->func, JS_UNDEFINED, countof(args), args);
44725-
JS_FreeValue(ctx, item);
44681+
selected = JS_Call(ctx, it->func, JS_UNDEFINED, countof(args), args);
4472644682
JS_FreeValue(ctx, index_val);
44727-
if (JS_IsException(ret))
44728-
goto fail;
44729-
if (!JS_IsObject(ret)) {
44730-
JS_FreeValue(ctx, ret);
44731-
JS_ThrowTypeError(ctx, "not an object");
44683+
if (JS_IsException(selected)) {
44684+
JS_FreeValue(ctx, item);
4473244685
goto fail;
4473344686
}
44734-
method = JS_GetProperty(ctx, ret, JS_ATOM_Symbol_iterator);
44735-
if (JS_IsException(method)) {
44736-
JS_FreeValue(ctx, ret);
44737-
goto fail;
44687+
if (JS_ToBoolFree(ctx, selected)) {
44688+
ret = item;
44689+
break;
4473844690
}
44739-
if (JS_IsNull(method) || JS_IsUndefined(method)) {
44740-
JS_FreeValue(ctx, method);
44741-
iter = ret;
44742-
} else {
44743-
iter = JS_GetIterator2(ctx, ret, method);
44744-
JS_FreeValue(ctx, method);
44745-
JS_FreeValue(ctx, ret);
44746-
if (JS_IsException(iter))
44691+
JS_FreeValue(ctx, item);
44692+
}
44693+
}
44694+
break;
44695+
case JS_ITERATOR_HELPER_KIND_FLAT_MAP:
44696+
{
44697+
JSValue item, method, index_val, iter;
44698+
JSValueConst args[2];
44699+
for(;;) {
44700+
if (JS_IsUndefined(it->inner)) {
44701+
item = JS_IteratorNext(ctx, it->obj, it->next, 0, NULL, pdone);
44702+
if (JS_IsException(item))
44703+
goto fail_no_close;
44704+
if (*pdone) {
44705+
ret = item;
44706+
break;
44707+
}
44708+
index_val = JS_NewInt64(ctx, it->count++);
44709+
args[0] = item;
44710+
args[1] = index_val;
44711+
ret = JS_Call(ctx, it->func, JS_UNDEFINED, countof(args), args);
44712+
JS_FreeValue(ctx, item);
44713+
JS_FreeValue(ctx, index_val);
44714+
if (JS_IsException(ret))
4474744715
goto fail;
44748-
}
44716+
if (!JS_IsObject(ret)) {
44717+
JS_FreeValue(ctx, ret);
44718+
JS_ThrowTypeError(ctx, "not an object");
44719+
goto fail;
44720+
}
44721+
method = JS_GetProperty(ctx, ret, JS_ATOM_Symbol_iterator);
44722+
if (JS_IsException(method)) {
44723+
JS_FreeValue(ctx, ret);
44724+
goto fail;
44725+
}
44726+
if (JS_IsNull(method) || JS_IsUndefined(method)) {
44727+
JS_FreeValue(ctx, method);
44728+
iter = ret;
44729+
} else {
44730+
iter = JS_GetIterator2(ctx, ret, method);
44731+
JS_FreeValue(ctx, method);
44732+
JS_FreeValue(ctx, ret);
44733+
if (JS_IsException(iter))
44734+
goto fail;
44735+
}
4474944736

44750-
it->inner = iter;
44751-
}
44737+
it->inner = iter;
44738+
method = JS_GetProperty(ctx, it->inner, JS_ATOM_next);
44739+
if (JS_IsException(method))
44740+
goto inner_fail;
44741+
it->inner_next = method;
44742+
}
4475244743

44753-
if (magic == GEN_MAGIC_NEXT)
44754-
method = JS_GetProperty(ctx, it->inner, JS_ATOM_next);
44755-
else
44756-
method = JS_GetProperty(ctx, it->inner, JS_ATOM_return);
44757-
if (JS_IsException(method)) {
44758-
inner_fail:
44759-
JS_IteratorClose(ctx, it->inner, FALSE);
44760-
JS_FreeValue(ctx, it->inner);
44761-
it->inner = JS_UNDEFINED;
44762-
goto fail;
44763-
}
44764-
if (magic == GEN_MAGIC_RETURN && (JS_IsUndefined(method) || JS_IsNull(method))) {
44765-
goto inner_end;
44766-
} else {
44767-
item = JS_IteratorNext(ctx, it->inner, method, 0, NULL, pdone);
44768-
JS_FreeValue(ctx, method);
44769-
if (JS_IsException(item))
44770-
goto inner_fail;
44771-
}
44772-
if (*pdone) {
44773-
inner_end:
44744+
item = JS_IteratorNext(ctx, it->inner, it->inner_next, 0, NULL, pdone);
44745+
if (JS_IsException(item)) {
44746+
inner_fail:
44747+
JS_IteratorClose(ctx, it->inner, FALSE);
44748+
JS_FreeValue(ctx, it->inner);
44749+
JS_FreeValue(ctx, it->inner_next);
44750+
it->inner = JS_UNDEFINED;
44751+
it->inner_next = JS_UNDEFINED;
44752+
goto fail;
44753+
}
44754+
if (!*pdone) {
44755+
ret = item;
44756+
break;
44757+
}
4477444758
*pdone = FALSE; // The outer iterator must continue.
4477544759
JS_IteratorClose(ctx, it->inner, FALSE);
4477644760
JS_FreeValue(ctx, it->inner);
44761+
JS_FreeValue(ctx, it->inner_next);
4477744762
it->inner = JS_UNDEFINED;
44778-
goto flat_map_again;
44763+
it->inner_next = JS_UNDEFINED;
4477944764
}
44780-
ret = item;
44781-
goto done;
4478244765
}
4478344766
break;
4478444767
case JS_ITERATOR_HELPER_KIND_MAP:
4478544768
{
44786-
JSValue item, method, index_val;
44769+
JSValue item, index_val;
4478744770
JSValueConst args[2];
44788-
if (magic == GEN_MAGIC_NEXT) {
44789-
method = JS_DupValue(ctx, it->next);
44790-
} else {
44791-
method = JS_GetProperty(ctx, it->obj, JS_ATOM_return);
44792-
if (JS_IsException(method))
44793-
goto fail;
44794-
}
44795-
item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone);
44796-
JS_FreeValue(ctx, method);
44771+
item = JS_IteratorNext(ctx, it->obj, it->next, 0, NULL, pdone);
4479744772
if (JS_IsException(item))
4479844773
goto fail_no_close;
44799-
if (*pdone || magic == GEN_MAGIC_RETURN) {
44774+
if (*pdone) {
4480044775
ret = item;
4480144776
goto done;
4480244777
}
@@ -44808,43 +44783,32 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val,
4480844783
JS_FreeValue(ctx, item);
4480944784
if (JS_IsException(ret))
4481044785
goto fail;
44811-
goto done;
4481244786
}
4481344787
break;
4481444788
case JS_ITERATOR_HELPER_KIND_TAKE:
4481544789
{
44816-
JSValue item, method;
44790+
JSValue item;
4481744791
if (it->count > 0) {
44818-
if (magic == GEN_MAGIC_NEXT) {
44819-
method = JS_DupValue(ctx, it->next);
44820-
} else {
44821-
method = JS_GetProperty(ctx, it->obj, JS_ATOM_return);
44822-
if (JS_IsException(method))
44823-
goto fail;
44824-
}
4482544792
it->count--;
44826-
item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone);
44827-
JS_FreeValue(ctx, method);
44793+
item = JS_IteratorNext(ctx, it->obj, it->next, 0, NULL, pdone);
4482844794
if (JS_IsException(item))
4482944795
goto fail_no_close;
4483044796
ret = item;
44831-
goto done;
44797+
} else {
44798+
*pdone = TRUE;
44799+
if (JS_IteratorClose(ctx, it->obj, FALSE))
44800+
ret = JS_EXCEPTION;
44801+
else
44802+
ret = JS_UNDEFINED;
4483244803
}
44833-
44834-
*pdone = TRUE;
44835-
if (JS_IteratorClose(ctx, it->obj, FALSE))
44836-
ret = JS_EXCEPTION;
44837-
else
44838-
ret = JS_UNDEFINED;
44839-
goto done;
4484044804
}
4484144805
break;
4484244806
default:
4484344807
abort();
4484444808
}
4484544809

4484644810
done:
44847-
it->done = magic == GEN_MAGIC_NEXT ? *pdone : 1;
44811+
it->done = *pdone;
4484844812
it->executing = 0;
4484944813
return ret;
4485044814
fail:

0 commit comments

Comments
 (0)