Skip to content

Commit 6d7448e

Browse files
committed
Implement Iterator.prototype.flatMap
1 parent 1cc19e4 commit 6d7448e

File tree

2 files changed

+94
-75
lines changed

2 files changed

+94
-75
lines changed

quickjs.c

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40284,7 +40284,13 @@ static JSValue js_iterator_proto_find(JSContext *ctx, JSValue this_val,
4028440284
static JSValue js_iterator_proto_flatMap(JSContext *ctx, JSValue this_val,
4028540285
int argc, JSValue *argv)
4028640286
{
40287-
return JS_ThrowInternalError(ctx, "TODO implement Iterator.prototype.flatMap");
40287+
JSValue func;
40288+
if (!JS_IsObject(this_val))
40289+
return JS_ThrowTypeError(ctx, "Iterator.prototype.flatMap called on non-object");
40290+
func = argv[0];
40291+
if (check_function(ctx, func))
40292+
return JS_EXCEPTION;
40293+
return js_create_iterator_helper(ctx, this_val, JS_ITERATOR_HELPER_KIND_FLAT_MAP, func, 0);
4028840294
}
4028940295

4029040296
static JSValue js_iterator_proto_forEach(JSContext *ctx, JSValue this_val,
@@ -40576,6 +40582,7 @@ typedef struct JSIteratorHelperData {
4057640582
JSValue obj;
4057740583
JSValue next;
4057840584
JSValue func; // predicate (filter) or mapper (flatMap, map)
40585+
JSValue inner; // innerValue (flatMap)
4057940586
int64_t count; // limit (drop, take) or counter (filter, map, flatMap)
4058040587
BOOL executing;
4058140588
BOOL done;
@@ -40589,6 +40596,7 @@ static void js_iterator_helper_finalizer(JSRuntime *rt, JSValue val)
4058940596
JS_FreeValueRT(rt, it->obj);
4059040597
JS_FreeValueRT(rt, it->func);
4059140598
JS_FreeValueRT(rt, it->next);
40599+
JS_FreeValueRT(rt, it->inner);
4059240600
js_free_rt(rt, it);
4059340601
}
4059440602
}
@@ -40602,6 +40610,7 @@ static void js_iterator_helper_mark(JSRuntime *rt, JSValue val,
4060240610
JS_MarkValue(rt, it->obj, mark_func);
4060340611
JS_MarkValue(rt, it->func, mark_func);
4060440612
JS_MarkValue(rt, it->next, mark_func);
40613+
JS_MarkValue(rt, it->inner, mark_func);
4060540614
}
4060640615
}
4060740616

@@ -40700,6 +40709,89 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValue this_val,
4070040709
goto filter_again;
4070140710
}
4070240711
break;
40712+
case JS_ITERATOR_HELPER_KIND_FLAT_MAP:
40713+
{
40714+
JSValue item, method, index_val, args[2], iter;
40715+
flat_map_again:
40716+
if (JS_IsUndefined(it->inner)) {
40717+
if (magic == GEN_MAGIC_NEXT) {
40718+
method = js_dup(it->next);
40719+
} else {
40720+
method = JS_GetProperty(ctx, it->obj, JS_ATOM_return);
40721+
if (JS_IsException(method))
40722+
goto fail;
40723+
}
40724+
item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone);
40725+
JS_FreeValue(ctx, method);
40726+
if (JS_IsException(item))
40727+
goto fail;
40728+
if (*pdone || magic == GEN_MAGIC_RETURN) {
40729+
ret = item;
40730+
goto done;
40731+
}
40732+
index_val = js_int64(it->count++);
40733+
args[0] = item;
40734+
args[1] = index_val;
40735+
ret = JS_Call(ctx, it->func, JS_UNDEFINED, countof(args), args);
40736+
JS_FreeValue(ctx, item);
40737+
JS_FreeValue(ctx, index_val);
40738+
if (JS_IsException(ret))
40739+
goto fail;
40740+
if (!JS_IsObject(ret)) {
40741+
JS_FreeValue(ctx, ret);
40742+
JS_ThrowTypeError(ctx, "not an object");
40743+
goto fail;
40744+
}
40745+
method = JS_GetProperty(ctx, ret, JS_ATOM_Symbol_iterator);
40746+
if (JS_IsException(method)) {
40747+
JS_FreeValue(ctx, ret);
40748+
goto fail;
40749+
}
40750+
if (JS_IsNull(method) || JS_IsUndefined(method)) {
40751+
JS_FreeValue(ctx, method);
40752+
iter = ret;
40753+
} else {
40754+
iter = JS_GetIterator2(ctx, ret, method);
40755+
JS_FreeValue(ctx, method);
40756+
JS_FreeValue(ctx, ret);
40757+
if (JS_IsException(iter))
40758+
goto fail;
40759+
}
40760+
40761+
it->inner = iter;
40762+
}
40763+
40764+
if (magic == GEN_MAGIC_NEXT)
40765+
method = JS_GetProperty(ctx, it->inner, JS_ATOM_next);
40766+
else
40767+
method = JS_GetProperty(ctx, it->inner, JS_ATOM_return);
40768+
if (JS_IsException(method)) {
40769+
inner_fail:
40770+
JS_IteratorClose(ctx, it->inner, FALSE);
40771+
JS_FreeValue(ctx, it->inner);
40772+
it->inner = JS_UNDEFINED;
40773+
goto fail;
40774+
}
40775+
if (magic == GEN_MAGIC_RETURN && (JS_IsUndefined(method) || JS_IsNull(method))) {
40776+
goto inner_end;
40777+
} else {
40778+
item = JS_IteratorNext(ctx, it->inner, method, 0, NULL, pdone);
40779+
JS_FreeValue(ctx, method);
40780+
if (JS_IsException(item))
40781+
goto inner_fail;
40782+
}
40783+
if (*pdone) {
40784+
inner_end:
40785+
*pdone = FALSE; // The outer iterator must continue.
40786+
JS_IteratorClose(ctx, it->inner, FALSE);
40787+
JS_FreeValue(ctx, it->inner);
40788+
it->inner = JS_UNDEFINED;
40789+
goto flat_map_again;
40790+
}
40791+
ret = item;
40792+
goto done;
40793+
}
40794+
break;
4070340795
case JS_ITERATOR_HELPER_KIND_MAP:
4070440796
{
4070540797
JSValue item, method, index_val, args[2];
@@ -40797,6 +40889,7 @@ static JSValue js_create_iterator_helper(JSContext *ctx, JSValue iterator,
4079740889
it->obj = js_dup(iterator);
4079840890
it->func = js_dup(func);
4079940891
it->next = method;
40892+
it->inner = JS_UNDEFINED;
4080040893
it->count = count;
4080140894
it->executing = FALSE;
4080240895
it->done = FALSE;

test262_errors.txt

Lines changed: 0 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -56,80 +56,6 @@ test262/test/built-ins/Iterator/prototype/constructor/prop-desc.js:10: Test262Er
5656
test262/test/built-ins/Iterator/prototype/constructor/prop-desc.js:10: strict mode: Test262Error: Expected SameValue(«"undefined"», «"function"») to be true
5757
test262/test/built-ins/Iterator/prototype/constructor/weird-setter.js:23: TypeError: cannot read property 'call' of undefined
5858
test262/test/built-ins/Iterator/prototype/constructor/weird-setter.js:23: strict mode: TypeError: cannot read property 'call' of undefined
59-
test262/test/built-ins/Iterator/prototype/flatMap/argument-effect-order.js:21: Test262Error: Expected a TypeError but got a InternalError
60-
test262/test/built-ins/Iterator/prototype/flatMap/argument-effect-order.js:21: strict mode: Test262Error: Expected a TypeError but got a InternalError
61-
test262/test/built-ins/Iterator/prototype/flatMap/callable.js:10: InternalError: TODO implement Iterator.prototype.flatMap
62-
test262/test/built-ins/Iterator/prototype/flatMap/callable.js:10: strict mode: InternalError: TODO implement Iterator.prototype.flatMap
63-
test262/test/built-ins/Iterator/prototype/flatMap/exhaustion-does-not-call-return.js:31: InternalError: TODO implement Iterator.prototype.flatMap
64-
test262/test/built-ins/Iterator/prototype/flatMap/exhaustion-does-not-call-return.js:31: strict mode: InternalError: TODO implement Iterator.prototype.flatMap
65-
test262/test/built-ins/Iterator/prototype/flatMap/flattens-iterable.js:22: InternalError: TODO implement Iterator.prototype.flatMap
66-
test262/test/built-ins/Iterator/prototype/flatMap/flattens-iterable.js:22: strict mode: InternalError: TODO implement Iterator.prototype.flatMap
67-
test262/test/built-ins/Iterator/prototype/flatMap/flattens-iterator.js:24: InternalError: TODO implement Iterator.prototype.flatMap
68-
test262/test/built-ins/Iterator/prototype/flatMap/flattens-iterator.js:24: strict mode: InternalError: TODO implement Iterator.prototype.flatMap
69-
test262/test/built-ins/Iterator/prototype/flatMap/flattens-only-depth-1.js:32: InternalError: TODO implement Iterator.prototype.flatMap
70-
test262/test/built-ins/Iterator/prototype/flatMap/flattens-only-depth-1.js:32: strict mode: InternalError: TODO implement Iterator.prototype.flatMap
71-
test262/test/built-ins/Iterator/prototype/flatMap/get-next-method-only-once.js:38: InternalError: TODO implement Iterator.prototype.flatMap
72-
test262/test/built-ins/Iterator/prototype/flatMap/get-next-method-only-once.js:38: strict mode: InternalError: TODO implement Iterator.prototype.flatMap
73-
test262/test/built-ins/Iterator/prototype/flatMap/get-next-method-throws.js:17: Test262Error: Expected a Test262Error but got a InternalError
74-
test262/test/built-ins/Iterator/prototype/flatMap/get-next-method-throws.js:17: strict mode: Test262Error: Expected a Test262Error but got a InternalError
75-
test262/test/built-ins/Iterator/prototype/flatMap/get-return-method-throws.js:25: InternalError: TODO implement Iterator.prototype.flatMap
76-
test262/test/built-ins/Iterator/prototype/flatMap/get-return-method-throws.js:25: strict mode: InternalError: TODO implement Iterator.prototype.flatMap
77-
test262/test/built-ins/Iterator/prototype/flatMap/iterable-primitives-are-not-flattened.js:32: Test262Error: Expected a TypeError but got a InternalError
78-
test262/test/built-ins/Iterator/prototype/flatMap/iterable-primitives-are-not-flattened.js:32: strict mode: Test262Error: Expected a TypeError but got a InternalError
79-
test262/test/built-ins/Iterator/prototype/flatMap/iterable-to-iterator-fallback.js:27: InternalError: TODO implement Iterator.prototype.flatMap
80-
test262/test/built-ins/Iterator/prototype/flatMap/iterable-to-iterator-fallback.js:27: strict mode: InternalError: TODO implement Iterator.prototype.flatMap
81-
test262/test/built-ins/Iterator/prototype/flatMap/iterator-already-exhausted.js:19: InternalError: TODO implement Iterator.prototype.flatMap
82-
test262/test/built-ins/Iterator/prototype/flatMap/iterator-already-exhausted.js:19: strict mode: InternalError: TODO implement Iterator.prototype.flatMap
83-
test262/test/built-ins/Iterator/prototype/flatMap/iterator-return-method-throws.js:25: InternalError: TODO implement Iterator.prototype.flatMap
84-
test262/test/built-ins/Iterator/prototype/flatMap/iterator-return-method-throws.js:25: strict mode: InternalError: TODO implement Iterator.prototype.flatMap
85-
test262/test/built-ins/Iterator/prototype/flatMap/mapper-args.js:24: InternalError: TODO implement Iterator.prototype.flatMap
86-
test262/test/built-ins/Iterator/prototype/flatMap/mapper-args.js:24: strict mode: InternalError: TODO implement Iterator.prototype.flatMap
87-
test262/test/built-ins/Iterator/prototype/flatMap/mapper-returns-closed-iterator.js:26: InternalError: TODO implement Iterator.prototype.flatMap
88-
test262/test/built-ins/Iterator/prototype/flatMap/mapper-returns-closed-iterator.js:26: strict mode: InternalError: TODO implement Iterator.prototype.flatMap
89-
test262/test/built-ins/Iterator/prototype/flatMap/mapper-returns-non-object.js:23: InternalError: TODO implement Iterator.prototype.flatMap
90-
test262/test/built-ins/Iterator/prototype/flatMap/mapper-returns-non-object.js:23: strict mode: InternalError: TODO implement Iterator.prototype.flatMap
91-
test262/test/built-ins/Iterator/prototype/flatMap/mapper-this.js:26: InternalError: TODO implement Iterator.prototype.flatMap
92-
test262/test/built-ins/Iterator/prototype/flatMap/mapper-this.js:26: strict mode: InternalError: TODO implement Iterator.prototype.flatMap
93-
test262/test/built-ins/Iterator/prototype/flatMap/mapper-throws-then-closing-iterator-also-throws.js:30: InternalError: TODO implement Iterator.prototype.flatMap
94-
test262/test/built-ins/Iterator/prototype/flatMap/mapper-throws-then-closing-iterator-also-throws.js:30: strict mode: InternalError: TODO implement Iterator.prototype.flatMap
95-
test262/test/built-ins/Iterator/prototype/flatMap/mapper-throws.js:31: InternalError: TODO implement Iterator.prototype.flatMap
96-
test262/test/built-ins/Iterator/prototype/flatMap/mapper-throws.js:31: strict mode: InternalError: TODO implement Iterator.prototype.flatMap
97-
test262/test/built-ins/Iterator/prototype/flatMap/next-method-returns-non-object.js:19: InternalError: TODO implement Iterator.prototype.flatMap
98-
test262/test/built-ins/Iterator/prototype/flatMap/next-method-returns-non-object.js:19: strict mode: InternalError: TODO implement Iterator.prototype.flatMap
99-
test262/test/built-ins/Iterator/prototype/flatMap/next-method-returns-throwing-done.js:27: InternalError: TODO implement Iterator.prototype.flatMap
100-
test262/test/built-ins/Iterator/prototype/flatMap/next-method-returns-throwing-done.js:27: strict mode: InternalError: TODO implement Iterator.prototype.flatMap
101-
test262/test/built-ins/Iterator/prototype/flatMap/next-method-returns-throwing-value-done.js:27: InternalError: TODO implement Iterator.prototype.flatMap
102-
test262/test/built-ins/Iterator/prototype/flatMap/next-method-returns-throwing-value-done.js:27: strict mode: InternalError: TODO implement Iterator.prototype.flatMap
103-
test262/test/built-ins/Iterator/prototype/flatMap/next-method-returns-throwing-value.js:27: InternalError: TODO implement Iterator.prototype.flatMap
104-
test262/test/built-ins/Iterator/prototype/flatMap/next-method-returns-throwing-value.js:27: strict mode: InternalError: TODO implement Iterator.prototype.flatMap
105-
test262/test/built-ins/Iterator/prototype/flatMap/next-method-throws.js:19: InternalError: TODO implement Iterator.prototype.flatMap
106-
test262/test/built-ins/Iterator/prototype/flatMap/next-method-throws.js:19: strict mode: InternalError: TODO implement Iterator.prototype.flatMap
107-
test262/test/built-ins/Iterator/prototype/flatMap/non-callable-mapper.js:18: Test262Error: Expected a TypeError but got a InternalError
108-
test262/test/built-ins/Iterator/prototype/flatMap/non-callable-mapper.js:18: strict mode: Test262Error: Expected a TypeError but got a InternalError
109-
test262/test/built-ins/Iterator/prototype/flatMap/result-is-iterator.js:12: InternalError: TODO implement Iterator.prototype.flatMap
110-
test262/test/built-ins/Iterator/prototype/flatMap/result-is-iterator.js:12: strict mode: InternalError: TODO implement Iterator.prototype.flatMap
111-
test262/test/built-ins/Iterator/prototype/flatMap/return-is-forwarded-to-mapper-result.js:19: InternalError: TODO implement Iterator.prototype.flatMap
112-
test262/test/built-ins/Iterator/prototype/flatMap/return-is-forwarded-to-mapper-result.js:19: strict mode: InternalError: TODO implement Iterator.prototype.flatMap
113-
test262/test/built-ins/Iterator/prototype/flatMap/return-is-forwarded-to-underlying-iterator.js:28: InternalError: TODO implement Iterator.prototype.flatMap
114-
test262/test/built-ins/Iterator/prototype/flatMap/return-is-forwarded-to-underlying-iterator.js:28: strict mode: InternalError: TODO implement Iterator.prototype.flatMap
115-
test262/test/built-ins/Iterator/prototype/flatMap/return-is-not-forwarded-after-exhaustion.js:27: InternalError: TODO implement Iterator.prototype.flatMap
116-
test262/test/built-ins/Iterator/prototype/flatMap/return-is-not-forwarded-after-exhaustion.js:27: strict mode: InternalError: TODO implement Iterator.prototype.flatMap
117-
test262/test/built-ins/Iterator/prototype/flatMap/strings-are-not-flattened.js:21: Test262Error: Expected a TypeError but got a InternalError
118-
test262/test/built-ins/Iterator/prototype/flatMap/strings-are-not-flattened.js:21: strict mode: Test262Error: Expected a TypeError but got a InternalError
119-
test262/test/built-ins/Iterator/prototype/flatMap/this-non-callable-next.js:13: InternalError: TODO implement Iterator.prototype.flatMap
120-
test262/test/built-ins/Iterator/prototype/flatMap/this-non-callable-next.js:13: strict mode: InternalError: TODO implement Iterator.prototype.flatMap
121-
test262/test/built-ins/Iterator/prototype/flatMap/this-non-object.js:21: Test262Error: Expected a TypeError but got a InternalError
122-
test262/test/built-ins/Iterator/prototype/flatMap/this-non-object.js:21: strict mode: Test262Error: Expected a TypeError but got a InternalError
123-
test262/test/built-ins/Iterator/prototype/flatMap/this-plain-iterator.js:24: InternalError: TODO implement Iterator.prototype.flatMap
124-
test262/test/built-ins/Iterator/prototype/flatMap/this-plain-iterator.js:24: strict mode: InternalError: TODO implement Iterator.prototype.flatMap
125-
test262/test/built-ins/Iterator/prototype/flatMap/throws-typeerror-when-generator-is-running.js:39: InternalError: TODO implement Iterator.prototype.flatMap
126-
test262/test/built-ins/Iterator/prototype/flatMap/throws-typeerror-when-generator-is-running.js:39: strict mode: InternalError: TODO implement Iterator.prototype.flatMap
127-
test262/test/built-ins/Iterator/prototype/flatMap/underlying-iterator-advanced-in-parallel.js:19: InternalError: TODO implement Iterator.prototype.flatMap
128-
test262/test/built-ins/Iterator/prototype/flatMap/underlying-iterator-advanced-in-parallel.js:19: strict mode: InternalError: TODO implement Iterator.prototype.flatMap
129-
test262/test/built-ins/Iterator/prototype/flatMap/underlying-iterator-closed-in-parallel.js:19: InternalError: TODO implement Iterator.prototype.flatMap
130-
test262/test/built-ins/Iterator/prototype/flatMap/underlying-iterator-closed-in-parallel.js:19: strict mode: InternalError: TODO implement Iterator.prototype.flatMap
131-
test262/test/built-ins/Iterator/prototype/flatMap/underlying-iterator-closed.js:21: InternalError: TODO implement Iterator.prototype.flatMap
132-
test262/test/built-ins/Iterator/prototype/flatMap/underlying-iterator-closed.js:21: strict mode: InternalError: TODO implement Iterator.prototype.flatMap
13359
test262/test/built-ins/Object/defineProperties/typedarray-backed-by-resizable-buffer.js:20: Test262Error: Expected a TypeError to be thrown but no exception was thrown at all
13460
test262/test/built-ins/Object/defineProperties/typedarray-backed-by-resizable-buffer.js:20: strict mode: Test262Error: Expected a TypeError to be thrown but no exception was thrown at all
13561
test262/test/built-ins/Object/defineProperty/coerced-P-grow.js:45: TypeError: out-of-bound index in typed array

0 commit comments

Comments
 (0)