From ec49af2e8cf93ea4b85e8fead934370449116428 Mon Sep 17 00:00:00 2001 From: jdalton Date: Sun, 29 Dec 2024 18:31:56 -0500 Subject: [PATCH] Update es-iterator-helpers concat --- .../Iterator.concat/implementation.js | 92 +++++++++++++------ 1 file changed, 62 insertions(+), 30 deletions(-) diff --git a/packages/npm/es-iterator-helpers/Iterator.concat/implementation.js b/packages/npm/es-iterator-helpers/Iterator.concat/implementation.js index 4fa5d876..3c677c2d 100644 --- a/packages/npm/es-iterator-helpers/Iterator.concat/implementation.js +++ b/packages/npm/es-iterator-helpers/Iterator.concat/implementation.js @@ -42,49 +42,81 @@ module.exports = '`Iterator.concat` requires all arguments to be iterable' ) } - // (Handled by getMethod, which throws if method is missing or not callable.) - records[i] = { - iterable, - openMethod: getMethod(iterable, SymbolIterator) - } + // Step 2.d: Append the Record { [[OpenMethod]]: method, [[Iterable]]: item } to iterables. + records[i] = { iterable, openMethod: method } } - let index = 0 - let innerIterator = null - // Step 3: Let closure be a new Abstract Closure that captures iterables. + + // Step 3: Let closure be a new Abstract Closure with no parameters that captures iterables and performs the following steps when called. + let iterablesIndex = 0 + let innerIteratorRecord const closure = { - // This closure will perform the steps defined in Step 3.a. next() { - while (index < length) { - if (!innerIterator) { - // If we haven't initialized an inner iterator yet, do so - const { iterable, openMethod } = records[index] - // Step 3.a.i: Let iter be Call(iterable.[[OpenMethod]], iterable.[[Iterable]]). - innerIterator = ReflectApply(openMethod, iterable, []) + // Step 3.a: For each Record iterable of iterables, do. + while (iterablesIndex < length) { + // Step 3.a.i: Let iter be ? Call(iterable.[[OpenMethod]], iterable.[[Iterable]]). + if (innerIteratorRecord === undefined) { + const { iterable, openMethod } = records[iterablesIndex] + const innerIterator = ReflectApply(openMethod, iterable, []) // Step 3.a.ii: If iter is not an Object, throw a TypeError exception. ensureObject(innerIterator, 'iterator') + // Step 3.a.iii: Let iteratorRecord be ? GetIteratorDirect(iter). + innerIteratorRecord = getIteratorDirect(innerIterator) } - // Step 3.a.iii: Let iteratorRecord be GetIteratorDirect(iter). - const { next } = getIteratorDirect(innerIterator) - // Step 3.a.iv: Let innerAlive be true. - // (Handled by the loop structure) - // Step 3.a.v: Repeat, while innerAlive is true. - const result = ReflectApply(next, innerIterator, []) - if (!result.done) { - // Step 3.a.v.3.a: Yield the value of the iterator. - return result + const { iterator, next } = innerIteratorRecord + try { + // Step 3.a.v.1: Let iteratorResult be ? IteratorStep(iteratorRecord). + const result = ReflectApply(next, iterator, []) + // Step 3.a.v.3: Yield value if not done. + if (!result.done) { + return { value: result.value, done: false } + } + } catch (error) { + // Step 3.a.v.3.b.i: Handle abrupt completion and rethrow error. + innerIteratorRecord = undefined + iterablesIndex += 1 + throw error } - // Step 3.a.v.2: If innerValue is done, move to the next iterable. - innerIterator = null - index += 1 + // Step 3.a.v.2: Set innerAlive to false and move to the next iterable. + innerIteratorRecord = undefined + iterablesIndex += 1 } // Step 3.b: Return Completion(undefined). return { value: undefined, done: true } + }, + + return() { + // Handle iterator return if it exists. + if (innerIteratorRecord) { + const { iterator } = innerIteratorRecord + innerIteratorRecord = undefined + const returnMethod = getMethod(iterator, 'return') + if (typeof returnMethod === 'function') { + return ReflectApply(returnMethod, iterator, []) + } + } + return { value: undefined, done: true } + }, + + throw(error) { + // Handle iterator throw if it exists. + if (innerIteratorRecord) { + const { iterator } = innerIteratorRecord + innerIteratorRecord = undefined + const throwMethod = getMethod(iterator, 'throw') + if (typeof throwMethod === 'function') { + return ReflectApply(throwMethod, iterator, [error]) + } + } + // Skip remaining iterables and propagate the error. + iterablesIndex = length + throw error } } - // Step 4: Create wrapper using CreateIteratorFromClosure. + + // Step 4: Let gen be CreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%, « [[UnderlyingIterators]] »). const wrapper = createIteratorFromClosure(closure) - // Step 5: Set wrapper.[[UnderlyingIterator]] to iteratorRecord. + // Step 5: Set gen.[[UnderlyingIterators]] to a new empty List. setUnderlyingIterator(wrapper, closure) - // Step 6: Return wrapper. + // Step 6: Return gen. return wrapper }