diff --git a/spec.emu b/spec.emu index cc1cfb5..c42bf43 100644 --- a/spec.emu +++ b/spec.emu @@ -14,14 +14,19 @@ copyright: false 1. Let _O_ be the *this* value. 1. If _O_ is not an Object, throw a *TypeError* exception. + 1. Let _iterated_ be the Iterator Record { [[Iterator]]: _O_, [[NextMethod]]: *undefined*, [[Done]]: *false* }. 1. If _skippedElements_ is *undefined*, then 1. Let _toSkip_ be 0. 1. Else, - 1. If _skippedElements_ is not one of *+∞𝔽*, *-∞𝔽*, or an integral Number, throw a *TypeError* exception. + 1. If _skippedElements_ is not one of *+∞𝔽*, *-∞𝔽*, or an integral Number, then + 1. Let _error_ be ThrowCompletion(a newly created *TypeError* object). + 1. Return ? IteratorClose(_iterated_, _error_). 1. Let _toSkip_ be the extended mathematical value of _skippedElements_. - 1. If _toSkip_ < 0, throw a *RangeError* exception. + 1. If _toSkip_ < 0, then + 1. Let _error_ be ThrowCompletion(a newly created *RangeError* object). + 1. Return ? IteratorClose(_iterated_, _error_). 1. Let _skipped_ be 0. - 1. Let _iterated_ be ? GetIteratorDirect(_O_). + 1. Set _iterated_ to ? GetIteratorDirect(_O_). 1. Repeat, 1. Let _value_ be ? IteratorStepValue(_iterated_). 1. If _value_ is ~done~, return *false*. diff --git a/src/index.ts b/src/index.ts index 4a7e4d2..996d6c7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,20 +2,27 @@ function includes(this: IterableIterator, searchElement: T, skippedElement let toSkip = 0; if (skippedElements !== undefined) { if (!(skippedElements === 2e308 || skippedElements === -2e308 || typeof skippedElements === 'number' && Math.trunc(skippedElements) === skippedElements)) { + try { this.return?.(); } catch {} throw new TypeError; } toSkip = skippedElements as number; } if (toSkip < 0) { + try { this.return?.(); } catch {} throw new RangeError; } let skipped = 0; - for (let e of this) { + let next = (Date.bind).call(this.next, this); + let iteratorResult = next(); + while (!iteratorResult.done) { + let e = iteratorResult.value; if (skipped < toSkip) { ++skipped; } else if ([e].includes(searchElement)) { + try { this.return?.(); } catch {} return true; } + iteratorResult = next(); } return false; } diff --git a/test/index.mjs b/test/index.mjs index 733f654..a21372d 100644 --- a/test/index.mjs +++ b/test/index.mjs @@ -56,7 +56,7 @@ test('zeroes', async t => { assert.equal(negative.values().includes(-0), true); }); -test('closes iterator', async t => { +test('closes iterator after succeeding', async t => { let closed = false; let i = 0; let iter = { @@ -67,7 +67,7 @@ test('closes iterator', async t => { }, return() { closed = true; - return { value: undefined, done: true }; + throw new Error; }, }; @@ -75,6 +75,50 @@ test('closes iterator', async t => { assert.equal(closed, true); }); +test('closes iterator after invalid second parameter', async t => { + { + let closed = false; + let i = 0; + let iter = { + __proto__: Iterator.prototype, + next() { + ++i; + return { value: i, done: false }; + }, + return() { + closed = true; + throw new Error; + }, + }; + + assert.throws(() => { + iter.includes(null, -2); + }, RangeError); + assert.equal(closed, true); + } + + { + let closed = false; + let i = 0; + let iter = { + __proto__: Iterator.prototype, + next() { + ++i; + return { value: i, done: false }; + }, + return() { + closed = true; + throw new Error; + }, + }; + + assert.throws(() => { + iter.includes(null, 'a string'); + }, TypeError); + assert.equal(closed, true); + } +}); + test('skipped elements', async t => { await test('negative integral', async t => { assert.throws(() => {