Skip to content

Commit

Permalink
Update es-iterator-helpers concat
Browse files Browse the repository at this point in the history
  • Loading branch information
jdalton committed Dec 29, 2024
1 parent bc755cb commit ec49af2
Showing 1 changed file with 62 additions and 30 deletions.
92 changes: 62 additions & 30 deletions packages/npm/es-iterator-helpers/Iterator.concat/implementation.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

0 comments on commit ec49af2

Please sign in to comment.