8000 Iterator functions: · bellard/quickjs@2d99c32 · GitHub
[go: up one dir, main page]

Skip to content

Commit 2d99c32

Browse files
author
Fabrice Bellard
committed
Iterator functions:
- removed memory leak - don't close iterator when IteratorStepValue fails - fixed Iterator Wrap next() and return() arguments - fixed Iterator.from()
1 parent cf0e179 commit 2d99c32

File tree

3 files changed

+75
-58
lines changed

3 files changed

+75
-58
lines changed

TODO

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,5 +62,5 @@ Optimization ideas:
6262
Test262o: 0/11262 errors, 463 excluded
6363
Test262o commit: 7da91bceb9ce7613f87db47ddd1292a2dda58b42 (es5-tests branch)
6464

65-
Result: 54/79801 errors, 1630 excluded, 6631 skipped
65+
Result: 54/80760 errors, 1631 excluded, 6064 skipped
6666
Test262 commit: e7e136756cd67c1ffcf7c09d03aeb8ad5a6cec0c

quickjs.c

Lines changed: 71 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -42176,7 +42176,7 @@ static JSValue js_array_iterator_next(JSContext *ctx, JSValueConst this_val,
4217642176
}
4217742177
}
4217842178

42179-
/* IteratorWrap */
42179+
/* Iterator Wrap */
4218042180

4218142181
typedef struct JSIteratorWrapData {
4218242182
JSValue wrapped_iter;
@@ -42214,18 +42214,20 @@ static JSValue js_iterator_wrap_next(JSContext *ctx, JSValueConst this_val,
4221442214
it = JS_GetOpaque2(ctx, this_val, JS_CLASS_ITERATOR_WRAP);
4221542215
if (!it)
4221642216
return JS_EXCEPTION;
42217-
if (magic == GEN_MAGIC_NEXT)
42218-
return JS_IteratorNext(ctx, it->wrapped_iter, it->wrapped_next, argc, argv, pdone);
42219-
method = JS_GetProperty(ctx, it->wrapped_iter, JS_ATOM_return);
42220-
if (JS_IsException(method))
42221-
return JS_EXCEPTION;
42222-
if (JS_IsNull(method) || JS_IsUndefined(method)) {
42223-
*pdone = TRUE;
42224-
return JS_UNDEFINED;
42217+
if (magic == GEN_MAGIC_NEXT) {
42218+
return JS_IteratorNext(ctx, it->wrapped_iter, it->wrapped_next, 0, NULL, pdone);
42219+
} else {
42220+
method = JS_GetProperty(ctx, it->wrapped_iter, JS_ATOM_return);
42221+
if (JS_IsException(method))
42222+
return JS_EXCEPTION;
42223+
if (JS_IsNull(method) || JS_IsUndefined(method)) {
42224+
*pdone = TRUE;
42225+
return JS_UNDEFINED;
42226+
}
42227+
ret = JS_IteratorNext2(ctx, it->wrapped_iter, method, 0, NULL, pdone);
42228+
JS_FreeValue(ctx, method);
42229+
return ret;
4222542230
}
42226-
ret = JS_IteratorNext2(ctx, it->wrapped_iter, method, argc, argv, pdone);
42227-
JS_FreeValue(ctx, method);
42228-
return ret;
4222942231
}
4223042232

4223142233
static const JSCFunctionListEntry js_iterator_wrap_proto_funcs[] = {
@@ -42275,50 +42277,55 @@ static JSValue js_iterator_constructor(JSContext *ctx, JSValueConst new_target,
4227542277
static JSValue js_iterator_from(JSContext *ctx, JSValueConst this_val,
4227642278
int argc, JSValueConst *argv)
4227742279
{
42278-
JSValue method, iter;
42280+
JSValueConst obj = argv[0];
42281+
JSValue method, iter, wrapper;
4227942282
JSIteratorWrapData *it;
4228042283
int ret;
4228142284

42282-
JSValueConst obj = argv[0];
42283-
if (JS_IsString(obj)) {
42284-
method = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_iterator);
42285-
if (JS_IsException(method))
42286-
return JS_EXCEPTION;
42287-
return JS_CallFree(ctx, method, obj, 0, NULL);
42285+
if (!JS_IsObject(obj)) {
42286+
if (!JS_IsString(obj))
42287+
return JS_ThrowTypeError(ctx, "Iterator.from called on non-object");
4228842288
}
42289-
if (!JS_IsObject(obj))
42290-
return JS_ThrowTypeError(ctx, "Iterator.from called on non-object");
42291-
ret = JS_OrdinaryIsInstanceOf(ctx, obj, ctx->iterator_ctor);
42292-
if (ret < 0)
42293-
return JS_EXCEPTION;
42294-
if (ret)
42295-
return JS_DupValue(ctx, obj);
4229642289
method = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_iterator);
4229742290
if (JS_IsException(method))
4229842291
return JS_EXCEPTION;
4229942292
if (JS_IsNull(method) || JS_IsUndefined(method)) {
42300-
method = JS_GetProperty(ctx, obj, JS_ATOM_next);
42301-
if (JS_IsException(method))
42302-
return JS_EXCEPTION;
42303-
iter = JS_NewObjectClass(ctx, JS_CLASS_ITERATOR_WRAP);
42304-
if (JS_IsException(iter))
42305-
goto fail;
42306-
it = js_malloc(ctx, sizeof(*it));
42307-
if (!it)
42308-
goto fail;
42309-
it->wrapped_iter = JS_DupValue(ctx, obj);
42310-
it->wrapped_next = method;
42311-
JS_SetOpaque(iter, it);
42293+
iter = JS_DupValue(ctx, obj);
4231242294
} else {
4231342295
iter = JS_GetIterator2(ctx, obj, method);
4231442296
JS_FreeValue(ctx, method);
4231542297
if (JS_IsException(iter))
4231642298
return JS_EXCEPTION;
4231742299
}
42318-
return iter;
42319-
fail:
42300+
42301+
wrapper = JS_UNDEFINED;
42302+
method = JS_GetProperty(ctx, iter, JS_ATOM_next);
42303+
if (JS_IsException(method))
42304+
goto fail;
42305+
42306+
ret = JS_OrdinaryIsInstanceOf(ctx, iter, ctx->iterator_ctor);
42307+
if (ret < 0)
42308+
goto fail;
42309+
if (ret) {
42310+
JS_FreeValue(ctx, method);
42311+
return iter;
42312+
}
42313+
42314+
wrapper = JS_NewObjectClass(ctx, JS_CLASS_ITERATOR_WRAP);
42315+
if (JS_IsException(wrapper))
42316+
goto fail;
42317+
it = js_malloc(ctx, sizeof(*it));
42318+
if (!it)
42319+
goto fail;
42320+
it->wrapped_iter = iter;
42321+
it->wrapped_next = method;
42322+
JS_SetOpaque(wrapper, it);
42323+
return wrapper;
42324+
42325+
fail:
4232042326
JS_FreeValue(ctx, method);
4232142327
JS_FreeValue(ctx, iter);
42328+
JS_FreeValue(ctx, wrapper);
4232242329
return JS_EXCEPTION;
4232342330
}
4232442331

@@ -42450,12 +42457,13 @@ static JSValue js_iterator_proto_func(JSContext *ctx, JSValueConst this_val,
4245042457
return JS_ThrowTypeErrorNotAnObject(ctx);
4245142458
func = JS_UNDEFINED;
4245242459
method = JS_UNDEFINED;
42460+
4245342461
if (check_function(ctx, argv[0]))
4245442462
goto fail;
4245542463
func = JS_DupValue(ctx, argv[0]);
4245642464
method = JS_GetProperty(ctx, this_val, JS_ATOM_next);
4245742465
if (JS_IsException(method))
42458-
goto fail;
42466+
goto fail_no_close;
4245942467

4246042468
r = JS_UNDEFINED;
4246142469

@@ -42466,7 +42474,7 @@ static JSValue js_iterator_proto_func(JSContext *ctx, JSValueConst this_val,
4246642474
for (idx = 0; /*empty*/; idx++) {
4246742475
item = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done);
4246842476
if (JS_IsException(item))
42469-
goto fail;
42477+
goto fail_no_close;
4247042478
if (done)
4247142479
break;
4247242480
index_val = JS_NewInt64(ctx, idx);
@@ -42495,7 +42503,7 @@ static JSValue js_iterator_proto_func(JSContext *ctx, JSValueConst this_val,
4249542503
for (idx = 0; /*empty*/; idx++) {
4249642504
item = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done);
4249742505
if (JS_IsException(item))
42498-
goto fail;
42506+
goto fail_no_close;
4249942507
if (done)
4250042508
break;
4250142509
index_val = JS_NewInt64(ctx, idx);
@@ -42516,6 +42524,7 @@ static JSValue js_iterator_proto_func(JSContext *ctx, JSValueConst this_val,
4251642524
}
4251742525
break;
4251842526
}
42527+
JS_FreeValue(ctx, item);
4251942528
index_val = JS_UNDEFINED;
4252042529
ret = JS_UNDEFINED;
4252142530
item = JS_UNDEFINED;
@@ -42527,7 +42536,7 @@ static JSValue js_iterator_proto_func(JSContext *ctx, JSValueConst this_val,
4252742536
for (idx = 0; /*empty*/; idx++) {
4252842537
item = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done);
4252942538
if (JS_IsException(item))
42530-
goto fail;
42539+
goto fail_no_close;
4253142540
if (done)
4253242541
break;
4253342542
index_val = JS_NewInt64(ctx, idx);
@@ -42551,7 +42560,7 @@ static JSValue js_iterator_proto_func(JSContext *ctx, JSValueConst this_val,
4255142560
for (idx = 0; /*empty*/; idx++) {
4255242561
item = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done);
4255342562
if (JS_IsException(item))
42554-
goto fail;
42563+
goto fail_no_close;
4255542564
if (done)
4255642565
break;
4255742566
index_val = JS_NewInt64(ctx, idx);
@@ -42583,8 +42592,9 @@ static JSValue js_iterator_proto_func(JSContext *ctx, JSValueConst this_val,
4258342592
JS_FreeValue(ctx, func);
4258442593
JS_FreeValue(ctx, method);
4258542594
return r;
42586-
fail:
42595+
fail:
4258742596
JS_IteratorClose(ctx, this_val, TRUE);
42597+
fail_no_close:
4258842598
JS_FreeValue(ctx, func);
4258942599
JS_FreeValue(ctx, method);
4259042600
return JS_EXCEPTION;
@@ -42615,7 +42625,7 @@ static JSValue js_iterator_proto_reduce(JSContext *ctx, JSValueConst this_val,
4261542625
} else {
4261642626
acc = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done);
4261742627
if (JS_IsException(acc))
42618-
goto exception;
42628+
goto exception_no_close;
4261942629
if (done) {
4262042630
JS_ThrowTypeError(ctx, "empty iterator");
4262142631
goto exception;
@@ -42625,7 +42635,7 @@ static JSValue js_iterator_proto_reduce(JSContext *ctx, JSValueConst this_val,
4262542635
for (/* empty */; /*empty*/; idx++) {
4262642636
item = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done);
4262742637
if (JS_IsException(item))
42628-
goto exception;
42638+
goto exception_no_close;
4262942639
if (done)
4263042640
break;
4263142641
index_val = JS_NewInt64(ctx, idx);
@@ -42646,8 +42656,9 @@ static JSValue js_iterator_proto_reduce(JSContext *ctx, JSValueConst this_val,
4264642656
JS_FreeValue(ctx, func);
4264742657
JS_FreeValue(ctx, method);
4264842658
return acc;
42649-
exception:
42659+
exception:
4265042660
JS_IteratorClose(ctx, this_val, TRUE);
42661+
exception_no_close:
4265142662
JS_FreeValue(ctx, acc);
4265242663
JS_FreeValue(ctx, func);
4265342664
JS_FreeValue(ctx, method);
@@ -42787,7 +42798,7 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val,
4278742798
item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone);
4278842799
if (JS_IsException(item)) {
4278942800
JS_FreeValue(ctx, method);
42790-
goto fail;
42801+
goto fail_no_close;
4279142802
}
4279242803
JS_FreeValue(ctx, item);
4279342804
if (magic == GEN_MAGIC_RETURN)
@@ -42802,7 +42813,7 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val,
4280242813
item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone);
4280342814
JS_FreeValue(ctx, method);
4280442815
if (JS_IsException(item))
42805-
goto fail;
42816+
goto fail_no_close;
4280642817
ret = item;
4280742818
goto done;
4280842819
}
@@ -42822,7 +42833,7 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val,
4282242833
item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone);
4282342834
if (JS_IsException(item)) {
4282442835
JS_FreeValue(ctx, method);
42825-
goto fail;
42836+
goto fail_no_close;
4282642837
}
4282742838
if (*pdone || magic == GEN_MAGIC_RETURN) {
4282842839
JS_FreeValue(ctx, method);
@@ -42835,6 +42846,7 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val,
4283542846
selected = JS_Call(ctx, it->func, JS_UNDEFINED, countof(args), args);
4283642847
JS_FreeValue(ctx, index_val);
4283742848
if (JS_IsException(selected)) {
42849+
JS_FreeValue(ctx, item);
4283842850
JS_FreeValue(ctx, method);
4283942851
goto fail;
4284042852
}
@@ -42843,6 +42855,7 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val,
4284342855
ret = item;
4284442856
goto done;
4284542857
}
42858+
JS_FreeValue(ctx, item);
4284642859
goto filter_again;
4284742860
}
4284842861
break;
@@ -42862,7 +42875,7 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val,
4286242875
item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone);
4286342876
JS_FreeValue(ctx, method);
4286442877
if (JS_IsException(item))
42865-
goto fail;
42878+
goto fail_no_close;
4286642879
if (*pdone || magic == GEN_MAGIC_RETURN) {
4286742880
ret = item;
4286842881
goto done;
@@ -42944,7 +42957,7 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val,
4294442957
item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone);
4294542958
JS_FreeValue(ctx, method);
4294642959
if (JS_IsException(item))
42947-
goto fail;
42960+
goto fail_no_close;
4294842961
if (*pdone || magic == GEN_MAGIC_RETURN) {
4294942962
ret = item;
4295042963
goto done;
@@ -42974,7 +42987,7 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val,
4297442987
item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone);
4297542988
JS_FreeValue(ctx, method);
4297642989
if (JS_IsException(item))
42977-
goto fail;
42990+
goto fail_no_close;
4297842991
ret = item;
4297942992
goto done;
4298042993
}
@@ -42991,13 +43004,14 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val,
4299143004
abort();
4299243005
}
4299343006

42994-
done:
43007+
done:
4299543008
it->done = magic == GEN_MAGIC_NEXT ? *pdone : 1;
4299643009
it->executing = 0;
4299743010
return ret;
42998-
fail:
43011+
fail:
4299943012
/* close the iterator object, preserving pending exception */
4300043013
JS_IteratorClose(ctx, it->obj, TRUE);
43014+
fail_no_close:
4300143015
ret = JS_EXCEPTION;
4300243016
goto done;
4300343017
}

test262.conf

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,9 @@ test262/test/built-ins/String/prototype/split/cstm-split-on-string-primitive.js
304304
# spec updates it in this case)
305305
test262/test/staging/sm/Array/frozen-dense-array.js
306306

307+
# does not match spec
308+
test262/test/staging/sm/Iterator/from/wrap-next-not-object-throws.js
309+
307310
# not supported
308311
test262/test/staging/sm/extensions/censor-strict-caller.js
309312
test262/test/staging/sm/JSON/parse-with-source.js

0 commit comments

Comments
 (0)
0