1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 23:17:46 +00:00

LibJS: Implement Iterator.from and the WrapForValidIteratorPrototype

Iterator.from creates an Iterator from either an existing iterator or
an iterator-like object. In the latter case, it sets the prototype of
the returned iterator to WrapForValidIteratorPrototype to wrap around
the iterator-like object's iteration methods.
This commit is contained in:
Timothy Flynn 2023-06-24 11:27:30 -04:00 committed by Andreas Kling
parent 5736b53013
commit d9d245faa7
11 changed files with 299 additions and 0 deletions

View file

@ -0,0 +1,109 @@
describe("errors", () => {
test("called with non-Object", () => {
expect(() => {
Iterator.from(Symbol.hasInstance);
}).toThrowWithMessage(TypeError, "obj is not an object");
});
test("@@iterator is not callable", () => {
const iterable = {};
iterable[Symbol.iterator] = 12389;
expect(() => {
Iterator.from(iterable);
}).toThrowWithMessage(TypeError, "12389 is not a function");
});
test("@@iterator throws an exception", () => {
function TestError() {}
const iterable = {};
iterable[Symbol.iterator] = () => {
throw new TestError();
};
expect(() => {
Iterator.from(iterable);
}).toThrow(TestError);
});
test("@@iterator return a non-Object", () => {
const iterable = {};
iterable[Symbol.iterator] = () => {
return Symbol.hasInstance;
};
expect(() => {
Iterator.from(iterable);
}).toThrowWithMessage(TypeError, "iterator is not an object");
});
});
describe("normal behavior", () => {
test("length is 1", () => {
expect(Iterator.from).toHaveLength(1);
});
test("create Iterator from a string", () => {
const iterator = Iterator.from("ab");
let result = iterator.next();
expect(result.value).toBe("a");
expect(result.done).toBeFalse();
result = iterator.next();
expect(result.value).toBe("b");
expect(result.done).toBeFalse();
result = iterator.next();
expect(result.value).toBeUndefined();
expect(result.done).toBeTrue();
});
test("create Iterator from generator", () => {
function* generator() {
yield 1;
yield 2;
}
const iterator = Iterator.from(generator());
let result = iterator.next();
expect(result.value).toBe(1);
expect(result.done).toBeFalse();
result = iterator.next();
expect(result.value).toBe(2);
expect(result.done).toBeFalse();
result = iterator.next();
expect(result.value).toBeUndefined();
expect(result.done).toBeTrue();
});
test("create Iterator from iterator-like object", () => {
class TestIterator {
next() {
if (this.#first) {
this.#first = false;
return { value: 1, done: false };
}
return { value: undefined, done: true };
}
#first = true;
}
const testIterator = new TestIterator();
const iterator = Iterator.from(testIterator);
let result = iterator.next();
expect(result.value).toBe(1);
expect(result.done).toBeFalse();
result = iterator.next();
expect(result.value).toBeUndefined();
expect(result.done).toBeTrue();
});
});