Skip to content

Commit 0362c0a

Browse files
authored
Implement Iterator.prototype.take (#676)
1 parent 4871290 commit 0362c0a

File tree

2 files changed

+71
-59
lines changed

2 files changed

+71
-59
lines changed

quickjs.c

+71-7
Original file line numberDiff line numberDiff line change
@@ -40060,9 +40060,10 @@ static JSValue js_iterator_proto_drop(JSContext *ctx, JSValue this_val,
4006040060
if (JS_ToInt64Free(ctx, &limit, v))
4006140061
return JS_EXCEPTION;
4006240062
}
40063-
if (limit < 0)
40063+
if (limit < 0) {
4006440064
fail:
4006540065
return JS_ThrowRangeError(ctx, "must be positive");
40066+
}
4006640067
return js_create_iterator_helper(ctx, this_val, JS_ITERATOR_HELPER_KIND_DROP, JS_UNDEFINED, limit);
4006740068
}
4006840069

@@ -40373,7 +40374,41 @@ static JSValue js_iterator_proto_some(JSContext *ctx, JSValue this_val,
4037340374
static JSValue js_iterator_proto_take(JSContext *ctx, JSValue this_val,
4037440375
int argc, JSValue *argv)
4037540376
{
40376-
return JS_ThrowInternalError(ctx, "TODO implement Iterator.prototype.take");
40377+
JSValue v;
40378+
double dlimit;
40379+
int64_t limit;
40380+
if (!JS_IsObject(this_val))
40381+
return JS_ThrowTypeError(ctx, "Iterator.prototype.take called on non-object");
40382+
v = JS_ToNumber(ctx, argv[0]);
40383+
if (JS_IsException(v))
40384+
return JS_EXCEPTION;
40385+
// Check for Infinity.
40386+
if (JS_ToFloat64(ctx, &dlimit, v)) {
40387+
JS_FreeValue(ctx, v);
40388+
return JS_EXCEPTION;
40389+
}
40390+
if (isnan(dlimit)) {
40391+
JS_FreeValue(ctx, v);
40392+
goto fail;
40393+
}
40394+
if (!isfinite(dlimit)) {
40395+
JS_FreeValue(ctx, v);
40396+
if (dlimit < 0)
40397+
goto fail;
40398+
else
40399+
limit = MAX_SAFE_INTEGER;
40400+
} else {
40401+
v = JS_ToIntegerFree(ctx, v);
40402+
if (JS_IsException(v))
40403+
return JS_EXCEPTION;
40404+
if (JS_ToInt64Free(ctx, &limit, v))
40405+
return JS_EXCEPTION;
40406+
}
40407+
if (limit < 0) {
40408+
fail:
40409+
return JS_ThrowRangeError(ctx, "must be positive");
40410+
}
40411+
return js_create_iterator_helper(ctx, this_val, JS_ITERATOR_HELPER_KIND_TAKE, JS_UNDEFINED, limit);
4037740412
}
4037840413

4037940414
static JSValue js_iterator_proto_toArray(JSContext *ctx, JSValue this_val,
@@ -40490,12 +40525,14 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValue this_val,
4049040525
JSIteratorHelperData *it;
4049140526
JSValue ret;
4049240527

40528+
*pdone = FALSE;
40529+
4049340530
it = JS_GetOpaque2(ctx, this_val, JS_CLASS_ITERATOR_HELPER);
4049440531
if (!it)
4049540532
goto fail;
4049640533
if (it->executing)
4049740534
return JS_ThrowTypeError(ctx, "cannot invoke a running iterator");
40498-
if (magic == GEN_MAGIC_RETURN && it->done)
40535+
if (it->done)
4049940536
return JS_UNDEFINED;
4050040537

4050140538
it->executing = TRUE;
@@ -40536,6 +40573,34 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValue this_val,
4053640573
goto done;
4053740574
}
4053840575
break;
40576+
case JS_ITERATOR_HELPER_KIND_TAKE:
40577+
{
40578+
JSValue item, method;
40579+
if (it->limit > 0) {
40580+
if (magic == GEN_MAGIC_NEXT) {
40581+
method = js_dup(it->next);
40582+
} else {
40583+
method = JS_GetProperty(ctx, it->obj, JS_ATOM_return);
40584+
if (JS_IsException(method))
40585+
goto fail;
40586+
}
40587+
it->limit--;
40588+
item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone);
40589+
JS_FreeValue(ctx, method);
40590+
if (JS_IsException(item))
40591+
goto fail;
40592+
ret = item;
40593+
goto done;
40594+
}
40595+
40596+
*pdone = TRUE;
40597+
if (JS_IteratorClose(ctx, it->obj, FALSE))
40598+
ret = JS_EXCEPTION;
40599+
else
40600+
ret = JS_UNDEFINED;
40601+
goto done;
40602+
}
40603+
break;
4053940604
default:
4054040605
abort();
4054140606
}
@@ -40545,13 +40610,12 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValue this_val,
4054540610
it->executing = FALSE;
4054640611
return ret;
4054740612
fail:
40548-
it->executing = FALSE;
40549-
if (it && JS_IsObject(it->obj)) {
40613+
if (it) {
4055040614
/* close the iterator object, preserving pending exception */
4055140615
JS_IteratorClose(ctx, it->obj, TRUE);
4055240616
}
40553-
*pdone = FALSE;
40554-
return JS_EXCEPTION;
40617+
ret = JS_EXCEPTION;
40618+
goto done;
4055540619
}
4055640620

4055740621
static JSValue js_create_iterator_helper(JSContext *ctx, JSValue iterator,

test262_errors.txt

-52
Original file line numberDiff line numberDiff line change
@@ -216,58 +216,6 @@ test262/test/built-ins/Iterator/prototype/map/underlying-iterator-closed-in-para
216216
test262/test/built-ins/Iterator/prototype/map/underlying-iterator-closed-in-parallel.js:19: strict mode: InternalError: TODO implement Iterator.prototype.map
217217
test262/test/built-ins/Iterator/prototype/map/underlying-iterator-closed.js:21: InternalError: TODO implement Iterator.prototype.map
218218
test262/test/built-ins/Iterator/prototype/map/underlying-iterator-closed.js:21: strict mode: InternalError: TODO implement Iterator.prototype.map
219-
test262/test/built-ins/Iterator/prototype/take/argument-effect-order.js:24: InternalError: TODO implement Iterator.prototype.take
220-
test262/test/built-ins/Iterator/prototype/take/argument-effect-order.js:24: strict mode: InternalError: TODO implement Iterator.prototype.take
221-
test262/test/built-ins/Iterator/prototype/take/callable.js:10: InternalError: TODO implement Iterator.prototype.take
222-
test262/test/built-ins/Iterator/prototype/take/callable.js:10: strict mode: InternalError: TODO implement Iterator.prototype.take
223-
test262/test/built-ins/Iterator/prototype/take/exhaustion-calls-return.js:35: InternalError: TODO implement Iterator.prototype.take
224-
test262/test/built-ins/Iterator/prototype/take/exhaustion-calls-return.js:35: strict mode: InternalError: TODO implement Iterator.prototype.take
225-
test262/test/built-ins/Iterator/prototype/take/get-next-method-only-once.js:38: InternalError: TODO implement Iterator.prototype.take
226-
test262/test/built-ins/Iterator/prototype/take/get-next-method-only-once.js:38: strict mode: InternalError: TODO implement Iterator.prototype.take
227-
test262/test/built-ins/Iterator/prototype/take/get-next-method-throws.js:17: Test262Error: Expected a Test262Error but got a InternalError
228-
test262/test/built-ins/Iterator/prototype/take/get-next-method-throws.js:17: strict mode: Test262Error: Expected a Test262Error but got a InternalError
229-
test262/test/built-ins/Iterator/prototype/take/get-return-method-throws.js:25: InternalError: TODO implement Iterator.prototype.take
230-
test262/test/built-ins/Iterator/prototype/take/get-return-method-throws.js:25: strict mode: InternalError: TODO implement Iterator.prototype.take
231-
test262/test/built-ins/Iterator/prototype/take/limit-greater-than-or-equal-to-total.js:23: InternalError: TODO implement Iterator.prototype.take
232-
test262/test/built-ins/Iterator/prototype/take/limit-greater-than-or-equal-to-total.js:23: strict mode: InternalError: TODO implement Iterator.prototype.take
233-
test262/test/built-ins/Iterator/prototype/take/limit-less-than-total.js:25: InternalError: TODO implement Iterator.prototype.take
234-
test262/test/built-ins/Iterator/prototype/take/limit-less-than-total.js:25: strict mode: InternalError: TODO implement Iterator.prototype.take
235-
test262/test/built-ins/Iterator/prototype/take/limit-rangeerror.js:18: InternalError: TODO implement Iterator.prototype.take
236-
test262/test/built-ins/Iterator/prototype/take/limit-rangeerror.js:18: strict mode: InternalError: TODO implement Iterator.prototype.take
237-
test262/test/built-ins/Iterator/prototype/take/limit-tonumber-throws.js:16: Test262Error: Expected a Test262Error but got a InternalError
238-
test262/test/built-ins/Iterator/prototype/take/limit-tonumber-throws.js:16: strict mode: Test262Error: Expected a Test262Error but got a InternalError
239-
test262/test/built-ins/Iterator/prototype/take/limit-tonumber.js:23: InternalError: TODO implement Iterator.prototype.take
240-
test262/test/built-ins/Iterator/prototype/take/limit-tonumber.js:23: strict mode: InternalError: TODO implement Iterator.prototype.take
241-
test262/test/built-ins/Iterator/prototype/take/next-method-returns-non-object.js:21: InternalError: TODO implement Iterator.prototype.take
242-
test262/test/built-ins/Iterator/prototype/take/next-method-returns-non-object.js:21: strict mode: InternalError: TODO implement Iterator.prototype.take
243-
test262/test/built-ins/Iterator/prototype/take/next-method-returns-throwing-done.js:32: InternalError: TODO implement Iterator.prototype.take
244-
test262/test/built-ins/Iterator/prototype/take/next-method-returns-throwing-done.js:32: strict mode: InternalError: TODO implement Iterator.prototype.take
245-
test262/test/built-ins/Iterator/prototype/take/next-method-returns-throwing-value-done.js:30: InternalError: TODO implement Iterator.prototype.take
246-
test262/test/built-ins/Iterator/prototype/take/next-method-returns-throwing-value-done.js:30: strict mode: InternalError: TODO implement Iterator.prototype.take
247-
test262/test/built-ins/Iterator/prototype/take/next-method-returns-throwing-value.js:32: InternalError: TODO implement Iterator.prototype.take
248-
test262/test/built-ins/Iterator/prototype/take/next-method-returns-throwing-value.js:32: strict mode: InternalError: TODO implement Iterator.prototype.take
249-
test262/test/built-ins/Iterator/prototype/take/next-method-throws.js:21: InternalError: TODO implement Iterator.prototype.take
250-
test262/test/built-ins/Iterator/prototype/take/next-method-throws.js:21: strict mode: InternalError: TODO implement Iterator.prototype.take
251-
test262/test/built-ins/Iterator/prototype/take/result-is-iterator.js:11: InternalError: TODO implement Iterator.prototype.take
252-
test262/test/built-ins/Iterator/prototype/take/result-is-iterator.js:11: strict mode: InternalError: TODO implement Iterator.prototype.take
253-
test262/test/built-ins/Iterator/prototype/take/return-is-forwarded.js:28: InternalError: TODO implement Iterator.prototype.take
254-
test262/test/built-ins/Iterator/prototype/take/return-is-forwarded.js:28: strict mode: InternalError: TODO implement Iterator.prototype.take
255-
test262/test/built-ins/Iterator/prototype/take/return-is-not-forwarded-after-exhaustion.js:27: InternalError: TODO implement Iterator.prototype.take
256-
test262/test/built-ins/Iterator/prototype/take/return-is-not-forwarded-after-exhaustion.js:27: strict mode: InternalError: TODO implement Iterator.prototype.take
257-
test262/test/built-ins/Iterator/prototype/take/this-non-callable-next.js:15: InternalError: TODO implement Iterator.prototype.take
258-
test262/test/built-ins/Iterator/prototype/take/this-non-callable-next.js:15: strict mode: InternalError: TODO implement Iterator.prototype.take
259-
test262/test/built-ins/Iterator/prototype/take/this-non-object.js:22: Test262Error: Expected a TypeError but got a InternalError
260-
test262/test/built-ins/Iterator/prototype/take/this-non-object.js:22: strict mode: Test262Error: Expected a TypeError but got a InternalError
261-
test262/test/built-ins/Iterator/prototype/take/this-plain-iterator.js:25: InternalError: TODO implement Iterator.prototype.take
262-
test262/test/built-ins/Iterator/prototype/take/this-plain-iterator.js:25: strict mode: InternalError: TODO implement Iterator.prototype.take
263-
test262/test/built-ins/Iterator/prototype/take/throws-typeerror-when-generator-is-running.js:33: InternalError: TODO implement Iterator.prototype.take
264-
test262/test/built-ins/Iterator/prototype/take/throws-typeerror-when-generator-is-running.js:33: strict mode: InternalError: TODO implement Iterator.prototype.take
265-
test262/test/built-ins/Iterator/prototype/take/underlying-iterator-advanced-in-parallel.js:19: InternalError: TODO implement Iterator.prototype.take
266-
test262/test/built-ins/Iterator/prototype/take/underlying-iterator-advanced-in-parallel.js:19: strict mode: InternalError: TODO implement Iterator.prototype.take
267-
test262/test/built-ins/Iterator/prototype/take/underlying-iterator-closed-in-parallel.js:19: InternalError: TODO implement Iterator.prototype.take
268-
test262/test/built-ins/Iterator/prototype/take/underlying-iterator-closed-in-parallel.js:19: strict mode: InternalError: TODO implement Iterator.prototype.take
269-
test262/test/built-ins/Iterator/prototype/take/underlying-iterator-closed.js:21: InternalError: TODO implement Iterator.prototype.take
270-
test262/test/built-ins/Iterator/prototype/take/underlying-iterator-closed.js:21: strict mode: InternalError: TODO implement Iterator.prototype.take
271219
test262/test/built-ins/RegExp/property-escapes/generated/Alphabetic.js:16: Test262Error: `\P{Alphabetic}` should match U+000363 (`ͣ`)
272220
test262/test/built-ins/RegExp/property-escapes/generated/Alphabetic.js:16: strict mode: Test262Error: `\P{Alphabetic}` should match U+000363 (`ͣ`)
273221
test262/test/built-ins/RegExp/property-escapes/generated/Assigned.js:16: Test262Error: `\P{Assigned}` should match U+001B7F (`᭿`)

0 commit comments

Comments
 (0)