]> git.kaiwu.me - quickjs.git/commitdiff
Iterator functions:
authorFabrice Bellard <fabrice@bellard.org>
Sat, 20 Sep 2025 16:30:02 +0000 (18:30 +0200)
committerFabrice Bellard <fabrice@bellard.org>
Sat, 20 Sep 2025 16:30:02 +0000 (18:30 +0200)
- removed memory leak
- don't close iterator when IteratorStepValue fails
- fixed  Iterator Wrap next() and return() arguments
- fixed Iterator.from()

TODO
quickjs.c
test262.conf

diff --git a/TODO b/TODO
index 2834dedd698035c2dbeb81d01ce84b6ff7d83396..7f8862123933ab7b622042ecc5f0d5c64963ea45 100644 (file)
--- a/TODO
+++ b/TODO
@@ -62,5 +62,5 @@ Optimization ideas:
 Test262o:   0/11262 errors, 463 excluded
 Test262o commit: 7da91bceb9ce7613f87db47ddd1292a2dda58b42 (es5-tests branch)
 
-Result: 54/79801 errors, 1630 excluded, 6631 skipped
+Result: 54/80760 errors, 1631 excluded, 6064 skipped
 Test262 commit: e7e136756cd67c1ffcf7c09d03aeb8ad5a6cec0c
index 7a203c6e25fd57d80b91b7324e95966b0c20e76e..244cc0e4081411b97571685b9906ab79a7cb6421 100644 (file)
--- a/quickjs.c
+++ b/quickjs.c
@@ -42176,7 +42176,7 @@ static JSValue js_array_iterator_next(JSContext *ctx, JSValueConst this_val,
     }
 }
 
-/* IteratorWrap */
+/* Iterator Wrap */
 
 typedef struct JSIteratorWrapData {
     JSValue wrapped_iter;
@@ -42214,18 +42214,20 @@ static JSValue js_iterator_wrap_next(JSContext *ctx, JSValueConst this_val,
     it = JS_GetOpaque2(ctx, this_val, JS_CLASS_ITERATOR_WRAP);
     if (!it)
         return JS_EXCEPTION;
-    if (magic == GEN_MAGIC_NEXT)
-        return JS_IteratorNext(ctx, it->wrapped_iter, it->wrapped_next, argc, argv, pdone);
-    method = JS_GetProperty(ctx, it->wrapped_iter, JS_ATOM_return);
-    if (JS_IsException(method))
-        return JS_EXCEPTION;
-    if (JS_IsNull(method) || JS_IsUndefined(method)) {
-        *pdone = TRUE;
-        return JS_UNDEFINED;
+    if (magic == GEN_MAGIC_NEXT) {
+        return JS_IteratorNext(ctx, it->wrapped_iter, it->wrapped_next, 0, NULL, pdone);
+    } else {
+        method = JS_GetProperty(ctx, it->wrapped_iter, JS_ATOM_return);
+        if (JS_IsException(method))
+            return JS_EXCEPTION;
+        if (JS_IsNull(method) || JS_IsUndefined(method)) {
+            *pdone = TRUE;
+            return JS_UNDEFINED;
+        }
+        ret = JS_IteratorNext2(ctx, it->wrapped_iter, method, 0, NULL, pdone);
+        JS_FreeValue(ctx, method);
+        return ret;
     }
-    ret = JS_IteratorNext2(ctx, it->wrapped_iter, method, argc, argv, pdone);
-    JS_FreeValue(ctx, method);
-    return ret;
 }
 
 static const JSCFunctionListEntry js_iterator_wrap_proto_funcs[] = {
@@ -42275,50 +42277,55 @@ static JSValue js_iterator_constructor(JSContext *ctx, JSValueConst new_target,
 static JSValue js_iterator_from(JSContext *ctx, JSValueConst this_val,
                                 int argc, JSValueConst *argv)
 {
-    JSValue method, iter;
+    JSValueConst obj = argv[0];
+    JSValue method, iter, wrapper;
     JSIteratorWrapData *it;
     int ret;
 
-    JSValueConst obj = argv[0];
-    if (JS_IsString(obj)) {
-        method = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_iterator);
-        if (JS_IsException(method))
-            return JS_EXCEPTION;
-        return JS_CallFree(ctx, method, obj, 0, NULL);
+    if (!JS_IsObject(obj)) {
+        if (!JS_IsString(obj))
+            return JS_ThrowTypeError(ctx, "Iterator.from called on non-object");
     }
-    if (!JS_IsObject(obj))
-        return JS_ThrowTypeError(ctx, "Iterator.from called on non-object");
-    ret = JS_OrdinaryIsInstanceOf(ctx, obj, ctx->iterator_ctor);
-    if (ret < 0)
-        return JS_EXCEPTION;
-    if (ret)
-        return JS_DupValue(ctx, obj);
     method = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_iterator);
     if (JS_IsException(method))
         return JS_EXCEPTION;
     if (JS_IsNull(method) || JS_IsUndefined(method)) {
-        method = JS_GetProperty(ctx, obj, JS_ATOM_next);
-        if (JS_IsException(method))
-            return JS_EXCEPTION;
-        iter = JS_NewObjectClass(ctx, JS_CLASS_ITERATOR_WRAP);
-        if (JS_IsException(iter))
-            goto fail;
-        it = js_malloc(ctx, sizeof(*it));
-        if (!it)
-            goto fail;
-        it->wrapped_iter = JS_DupValue(ctx, obj);
-        it->wrapped_next = method;
-        JS_SetOpaque(iter, it);
+        iter = JS_DupValue(ctx, obj);
     } else {
         iter = JS_GetIterator2(ctx, obj, method);
         JS_FreeValue(ctx, method);
         if (JS_IsException(iter))
             return JS_EXCEPTION;
     }
-    return iter;
-fail:
+
+    wrapper = JS_UNDEFINED;
+    method = JS_GetProperty(ctx, iter, JS_ATOM_next);
+    if (JS_IsException(method))
+        goto fail;
+
+    ret = JS_OrdinaryIsInstanceOf(ctx, iter, ctx->iterator_ctor);
+    if (ret < 0)
+        goto fail;
+    if (ret) {
+        JS_FreeValue(ctx, method);
+        return iter;
+    }
+    
+    wrapper = JS_NewObjectClass(ctx, JS_CLASS_ITERATOR_WRAP);
+    if (JS_IsException(wrapper))
+        goto fail;
+    it = js_malloc(ctx, sizeof(*it));
+    if (!it)
+        goto fail;
+    it->wrapped_iter = iter;
+    it->wrapped_next = method;
+    JS_SetOpaque(wrapper, it);
+    return wrapper;
+
+ fail:
     JS_FreeValue(ctx, method);
     JS_FreeValue(ctx, iter);
+    JS_FreeValue(ctx, wrapper);
     return JS_EXCEPTION;
 }
 
@@ -42450,12 +42457,13 @@ static JSValue js_iterator_proto_func(JSContext *ctx, JSValueConst this_val,
         return JS_ThrowTypeErrorNotAnObject(ctx);
     func = JS_UNDEFINED;
     method = JS_UNDEFINED;
+    
     if (check_function(ctx, argv[0]))
         goto fail;
     func = JS_DupValue(ctx, argv[0]);
     method = JS_GetProperty(ctx, this_val, JS_ATOM_next);
     if (JS_IsException(method))
-        goto fail;
+        goto fail_no_close;
 
     r = JS_UNDEFINED;
 
@@ -42466,7 +42474,7 @@ static JSValue js_iterator_proto_func(JSContext *ctx, JSValueConst this_val,
             for (idx = 0; /*empty*/; idx++) {
                 item = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done);
                 if (JS_IsException(item))
-                    goto fail;
+                    goto fail_no_close;
                 if (done)
                     break;
                 index_val = JS_NewInt64(ctx, idx);
@@ -42495,7 +42503,7 @@ static JSValue js_iterator_proto_func(JSContext *ctx, JSValueConst this_val,
             for (idx = 0; /*empty*/; idx++) {
                 item = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done);
                 if (JS_IsException(item))
-                    goto fail;
+                    goto fail_no_close;
                 if (done)
                     break;
                 index_val = JS_NewInt64(ctx, idx);
@@ -42516,6 +42524,7 @@ static JSValue js_iterator_proto_func(JSContext *ctx, JSValueConst this_val,
                     }
                     break;
                 }
+                JS_FreeValue(ctx, item);
                 index_val = JS_UNDEFINED;
                 ret = JS_UNDEFINED;
                 item = JS_UNDEFINED;
@@ -42527,7 +42536,7 @@ static JSValue js_iterator_proto_func(JSContext *ctx, JSValueConst this_val,
             for (idx = 0; /*empty*/; idx++) {
                 item = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done);
                 if (JS_IsException(item))
-                    goto fail;
+                    goto fail_no_close;
                 if (done)
                     break;
                 index_val = JS_NewInt64(ctx, idx);
@@ -42551,7 +42560,7 @@ static JSValue js_iterator_proto_func(JSContext *ctx, JSValueConst this_val,
             for (idx = 0; /*empty*/; idx++) {
                 item = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done);
                 if (JS_IsException(item))
-                    goto fail;
+                    goto fail_no_close;
                 if (done)
                     break;
                 index_val = JS_NewInt64(ctx, idx);
@@ -42583,8 +42592,9 @@ static JSValue js_iterator_proto_func(JSContext *ctx, JSValueConst this_val,
     JS_FreeValue(ctx, func);
     JS_FreeValue(ctx, method);
     return r;
-fail:
+ fail:
     JS_IteratorClose(ctx, this_val, TRUE);
+ fail_no_close:
     JS_FreeValue(ctx, func);
     JS_FreeValue(ctx, method);
     return JS_EXCEPTION;
@@ -42615,7 +42625,7 @@ static JSValue js_iterator_proto_reduce(JSContext *ctx, JSValueConst this_val,
     } else {
         acc = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done);
         if (JS_IsException(acc))
-            goto exception;
+            goto exception_no_close;
         if (done) {
             JS_ThrowTypeError(ctx, "empty iterator");
             goto exception;
@@ -42625,7 +42635,7 @@ static JSValue js_iterator_proto_reduce(JSContext *ctx, JSValueConst this_val,
     for (/* empty */; /*empty*/; idx++) {
         item = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done);
         if (JS_IsException(item))
-            goto exception;
+            goto exception_no_close;
         if (done)
             break;
         index_val = JS_NewInt64(ctx, idx);
@@ -42646,8 +42656,9 @@ static JSValue js_iterator_proto_reduce(JSContext *ctx, JSValueConst this_val,
     JS_FreeValue(ctx, func);
     JS_FreeValue(ctx, method);
     return acc;
-exception:
+ exception:
     JS_IteratorClose(ctx, this_val, TRUE);
+ exception_no_close:
     JS_FreeValue(ctx, acc);
     JS_FreeValue(ctx, func);
     JS_FreeValue(ctx, method);
@@ -42787,7 +42798,7 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val,
                 item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone);
                 if (JS_IsException(item)) {
                     JS_FreeValue(ctx, method);
-                    goto fail;
+                    goto fail_no_close;
                 }
                 JS_FreeValue(ctx, item);
                 if (magic == GEN_MAGIC_RETURN)
@@ -42802,7 +42813,7 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val,
             item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone);
             JS_FreeValue(ctx, method);
             if (JS_IsException(item))
-                goto fail;
+                goto fail_no_close;
             ret = item;
             goto done;
         }
@@ -42822,7 +42833,7 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val,
             item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone);
             if (JS_IsException(item)) {
                 JS_FreeValue(ctx, method);
-                goto fail;
+                goto fail_no_close;
             }
             if (*pdone || magic == GEN_MAGIC_RETURN) {
                 JS_FreeValue(ctx, method);
@@ -42835,6 +42846,7 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val,
             selected = JS_Call(ctx, it->func, JS_UNDEFINED, countof(args), args);
             JS_FreeValue(ctx, index_val);
             if (JS_IsException(selected)) {
+                JS_FreeValue(ctx, item);
                 JS_FreeValue(ctx, method);
                 goto fail;
             }
@@ -42843,6 +42855,7 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val,
                 ret = item;
                 goto done;
             }
+            JS_FreeValue(ctx, item);
             goto filter_again;
         }
         break;
@@ -42862,7 +42875,7 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val,
                 item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone);
                 JS_FreeValue(ctx, method);
                 if (JS_IsException(item))
-                    goto fail;
+                    goto fail_no_close;
                 if (*pdone || magic == GEN_MAGIC_RETURN) {
                     ret = item;
                     goto done;
@@ -42944,7 +42957,7 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val,
             item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone);
             JS_FreeValue(ctx, method);
             if (JS_IsException(item))
-                goto fail;
+                goto fail_no_close;
             if (*pdone || magic == GEN_MAGIC_RETURN) {
                 ret = item;
                 goto done;
@@ -42974,7 +42987,7 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val,
                 item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone);
                 JS_FreeValue(ctx, method);
                 if (JS_IsException(item))
-                    goto fail;
+                    goto fail_no_close;
                 ret = item;
                 goto done;
             }
@@ -42991,13 +43004,14 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val,
         abort();
     }
 
-done:
+ done:
     it->done = magic == GEN_MAGIC_NEXT ? *pdone : 1;
     it->executing = 0;
     return ret;
-fail:
+ fail:
     /* close the iterator object, preserving pending exception */
     JS_IteratorClose(ctx, it->obj, TRUE);
+ fail_no_close:
     ret = JS_EXCEPTION;
     goto done;
 }
index f955c6c6e83eaac45e0043da183fb1539b081656..2a1d5311bf939eb8e07bbeb415523ef28d848607 100644 (file)
@@ -304,6 +304,9 @@ test262/test/built-ins/String/prototype/split/cstm-split-on-string-primitive.js
 # spec updates it in this case)
 test262/test/staging/sm/Array/frozen-dense-array.js
 
+# does not match spec
+test262/test/staging/sm/Iterator/from/wrap-next-not-object-throws.js
+
 # not supported
 test262/test/staging/sm/extensions/censor-strict-caller.js
 test262/test/staging/sm/JSON/parse-with-source.js