mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 15:27:35 +00:00
LibJS: Implement Iterator.prototype.toArray
This commit is contained in:
parent
acc05480e8
commit
35380b2aef
4 changed files with 94 additions and 0 deletions
|
@ -512,6 +512,7 @@ namespace JS {
|
|||
P(timeZone) \
|
||||
P(timeZoneName) \
|
||||
P(timeZones) \
|
||||
P(toArray) \
|
||||
P(toDateString) \
|
||||
P(toExponential) \
|
||||
P(toFixed) \
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <AK/Function.h>
|
||||
#include <LibJS/Runtime/AbstractOperations.h>
|
||||
#include <LibJS/Runtime/Array.h>
|
||||
#include <LibJS/Runtime/FunctionObject.h>
|
||||
#include <LibJS/Runtime/GlobalObject.h>
|
||||
#include <LibJS/Runtime/IteratorHelper.h>
|
||||
|
@ -36,6 +37,7 @@ ThrowCompletionOr<void> IteratorPrototype::initialize(Realm& realm)
|
|||
define_native_function(realm, vm.names.drop, drop, 1, attr);
|
||||
define_native_function(realm, vm.names.flatMap, flat_map, 1, attr);
|
||||
define_native_function(realm, vm.names.reduce, reduce, 1, attr);
|
||||
define_native_function(realm, vm.names.toArray, to_array, 0, attr);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
@ -516,4 +518,36 @@ JS_DEFINE_NATIVE_FUNCTION(IteratorPrototype::reduce)
|
|||
}
|
||||
}
|
||||
|
||||
// 3.1.3.8 Iterator.prototype.toArray ( ), https://tc39.es/proposal-iterator-helpers/#sec-iteratorprototype.toarray
|
||||
JS_DEFINE_NATIVE_FUNCTION(IteratorPrototype::to_array)
|
||||
{
|
||||
auto& realm = *vm.current_realm();
|
||||
|
||||
// 1. Let O be the this value.
|
||||
// 2. If O is not an Object, throw a TypeError exception.
|
||||
auto object = TRY(this_object(vm));
|
||||
|
||||
// 3. Let iterated be ? GetIteratorDirect(O).
|
||||
auto iterated = TRY(get_iterator_direct(vm, object));
|
||||
|
||||
// 4. Let items be a new empty List.
|
||||
Vector<Value> items;
|
||||
|
||||
// 5. Repeat,
|
||||
while (true) {
|
||||
// a. Let next be ? IteratorStep(iterated).
|
||||
auto next = TRY(iterator_step(vm, iterated));
|
||||
|
||||
// b. If next is false, return CreateArrayFromList(items).
|
||||
if (!next)
|
||||
return Array::create_from(realm, items);
|
||||
|
||||
// c. Let value be ? IteratorValue(next).
|
||||
auto value = TRY(iterator_value(vm, *next));
|
||||
|
||||
// d. Append value to items.
|
||||
TRY_OR_THROW_OOM(vm, items.try_append(value));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ private:
|
|||
JS_DECLARE_NATIVE_FUNCTION(drop);
|
||||
JS_DECLARE_NATIVE_FUNCTION(flat_map);
|
||||
JS_DECLARE_NATIVE_FUNCTION(reduce);
|
||||
JS_DECLARE_NATIVE_FUNCTION(to_array);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
describe("errors", () => {
|
||||
test("iterator's next method throws", () => {
|
||||
function TestError() {}
|
||||
|
||||
class TestIterator extends Iterator {
|
||||
next() {
|
||||
throw new TestError();
|
||||
}
|
||||
}
|
||||
|
||||
expect(() => {
|
||||
new TestIterator().toArray();
|
||||
}).toThrow(TestError);
|
||||
});
|
||||
|
||||
test("value returned by iterator's next method throws", () => {
|
||||
function TestError() {}
|
||||
|
||||
class TestIterator extends Iterator {
|
||||
next() {
|
||||
return {
|
||||
done: false,
|
||||
get value() {
|
||||
throw new TestError();
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
expect(() => {
|
||||
new TestIterator().toArray();
|
||||
}).toThrow(TestError);
|
||||
});
|
||||
});
|
||||
|
||||
describe("normal behavior", () => {
|
||||
test("length is 0", () => {
|
||||
expect(Iterator.prototype.toArray).toHaveLength(0);
|
||||
});
|
||||
|
||||
test("empty list", () => {
|
||||
function* generator() {}
|
||||
|
||||
const result = generator().toArray();
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
|
||||
test("non-empty list", () => {
|
||||
function* generator() {
|
||||
yield 1;
|
||||
yield 2;
|
||||
yield 3;
|
||||
}
|
||||
|
||||
const result = generator().toArray();
|
||||
expect(result).toEqual([1, 2, 3]);
|
||||
});
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue