%PDF- %PDF-
Direktori : /home/vacivi36/vittasync.vacivitta.com.br/vittasync/node/deps/v8/src/builtins/ |
Current File : /home/vacivi36/vittasync.vacivitta.com.br/vittasync/node/deps/v8/src/builtins/iterator-helpers.tq |
// Copyright 2023 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // --- Utilities namespace iterator { // Iterator helpers are specced as generators but implemented as direct // iterators. As such generator states need to be tracked manually. To save // space, this is done by assigning sentinel values to underlying.next. // Tracks the ~completed~ generator state. const kIteratorHelperExhausted: Null = Null; // Tracks the ~executing~ generator state. const kIteratorHelperExecuting: Undefined = Undefined; macro IsIteratorHelperExhausted(helper: JSIteratorHelper): bool { return helper.underlying.next == kIteratorHelperExhausted; } macro MarkIteratorHelperAsExhausted(helper: JSIteratorHelper): void { helper.underlying.next = kIteratorHelperExhausted; } macro IsIteratorHelperExecuting(helper: JSIteratorHelper): bool { return helper.underlying.next == kIteratorHelperExecuting; } // When a generator's state is ~executing~, attempts to reenter via next() or // return() throw a TypeError. See step 6 in ES #sec-generatorvalidate. macro ThrowIfIteratorHelperExecuting( implicit context: Context)(helper: JSIteratorHelper): void { if (IsIteratorHelperExecuting(helper)) { ThrowTypeError(MessageTemplate::kGeneratorRunning); } } macro MarkIteratorHelperAsExecuting(helper: JSIteratorHelper): IteratorRecord { dcheck(!IsIteratorHelperExecuting(helper)); const underlying = helper.underlying; helper.underlying.next = kIteratorHelperExecuting; return underlying; } macro MarkIteratorHelperAsFinishedExecuting( helper: JSIteratorHelper, underlying: IteratorRecord): void { dcheck(IsIteratorHelperExecuting(helper)); dcheck(underlying.next != kIteratorHelperExecuting); dcheck(underlying.object == helper.underlying.object); helper.underlying.next = underlying.next; } // https://tc39.es/proposal-iterator-helpers/#sec-getiteratordirect transitioning macro GetIteratorDirect( implicit context: Context)(obj: JSReceiver): IteratorRecord { // 1. Let nextMethod be ? Get(obj, "next"). const nextMethod = GetProperty(obj, kNextString); // 2. Let iteratorRecord be Record { [[Iterator]]: obj, [[NextMethod]]: // nextMethod, [[Done]]: false }. // 3. Return iteratorRecord. return IteratorRecord{object: obj, next: nextMethod}; } // --- Dispatch functions for all iterator helpers // https://tc39.es/proposal-iterator-helpers/#sec-%iteratorhelperprototype%.next transitioning javascript builtin IteratorHelperPrototypeNext( js-implicit context: NativeContext, receiver: JSAny)(): JSAny { // 1. Return ? GeneratorResume(this value, undefined, "Iterator Helper"). // Iterator helpers are specified as generators but we implement them as // direct iterators. const helper = Cast<JSIteratorHelper>(receiver) otherwise ThrowTypeError( MessageTemplate::kIncompatibleMethodReceiver, 'Iterator Helper.prototype.next', receiver); ThrowIfIteratorHelperExecuting(helper); if (IsIteratorHelperExhausted(helper)) { return AllocateJSIteratorResult(Undefined, True); } typeswitch (helper) { case (mapHelper: JSIteratorMapHelper): { return IteratorMapHelperNext(mapHelper); } case (filterHelper: JSIteratorFilterHelper): { return IteratorFilterHelperNext(filterHelper); } case (takeHelper: JSIteratorTakeHelper): { return IteratorTakeHelperNext(takeHelper); } case (dropHelper: JSIteratorDropHelper): { return IteratorDropHelperNext(dropHelper); } case (flatMapHelper: JSIteratorFlatMapHelper): { return IteratorFlatMapHelperNext(flatMapHelper); } case (Object): { unreachable; } } } // https://tc39.es/proposal-iterator-helpers/#sec-%iteratorhelperprototype%.return transitioning javascript builtin IteratorHelperPrototypeReturn( js-implicit context: NativeContext, receiver: JSAny)(): JSObject { // 1. Let O be this value. // 2. Perform ? RequireInternalSlot(O, [[UnderlyingIterator]]). // 3. Assert: O has a [[GeneratorState]] slot. // 4. If O.[[GeneratorState]] is suspendedStart, then // a. Set O.[[GeneratorState]] to completed. // b. Perform ? IteratorClose(O.[[UnderlyingIterator]], // NormalCompletion(unused)). // c. Return CreateIterResultObject(undefined, true). // 5. Let C be Completion { [[Type]]: return, [[Value]]: undefined, // [[Target]]: empty }. // 6. Return ? GeneratorResumeAbrupt(O, C, "Iterator Helper"). // Return for flatMap helper is not the same as other helpers. typeswitch (receiver) { case (helper: JSIteratorFlatMapHelper): { ThrowIfIteratorHelperExecuting(helper); if (IsIteratorHelperExhausted(helper)) { return AllocateJSIteratorResult(Undefined, True); } MarkIteratorHelperAsExhausted(helper); if (helper.innerAlive == True) { try { // d. If completion is an abrupt completion, then // i. Let backupCompletion be Completion(IteratorClose(innerIterator, // completion)). IteratorClose(helper.innerIterator); } catch (e, message) { // ii. IfAbruptCloseIterator(backupCompletion, iterated). IteratorCloseOnException(helper.underlying); ReThrowWithMessage(context, e, message); } } // iii. Return ? IteratorClose(completion, iterated). IteratorClose(helper.underlying); return AllocateJSIteratorResult(Undefined, True); } case (Object): { // Iterator helpers are specified as generators. The net effect of this // method is to close the underlying and return { value: undefined, done: // true }. const helper = Cast<JSIteratorHelper>(receiver) otherwise ThrowTypeError( MessageTemplate::kIncompatibleMethodReceiver, 'Iterator Helper.prototype.return', receiver); ThrowIfIteratorHelperExecuting(helper); if (!IsIteratorHelperExhausted(helper)) { MarkIteratorHelperAsExhausted(helper); IteratorClose(helper.underlying); } return AllocateJSIteratorResult(Undefined, True); } } } // --- map helper macro NewJSIteratorMapHelper( implicit context: Context)(underlying: IteratorRecord, mapper: Callable): JSIteratorMapHelper { return new JSIteratorMapHelper{ map: *NativeContextSlot(ContextSlot::ITERATOR_MAP_HELPER_MAP_INDEX), properties_or_hash: kEmptyFixedArray, elements: kEmptyFixedArray, underlying: underlying, mapper: mapper, counter: 0 }; } // https://tc39.es/proposal-iterator-helpers/#sec-iteratorprototype.map transitioning javascript builtin IteratorPrototypeMap( js-implicit context: NativeContext, receiver: JSAny)( mapper: JSAny): JSIteratorMapHelper { const methodName: constexpr string = 'Iterator.prototype.map'; // 1. Let O be the this value. // 2. If O is not an Object, throw a TypeError exception. const o = Cast<JSReceiver>(receiver) otherwise ThrowTypeError(MessageTemplate::kCalledOnNonObject, methodName); // 3. If IsCallable(mapper) is false, throw a TypeError exception. const mapper = Cast<Callable>(mapper) otherwise ThrowCalledNonCallable(methodName); // 4. Let iterated be ? GetIteratorDirect(O). const iterated = GetIteratorDirect(o); // Step 5 implemented in IteratorMapHelperNext // 6. Let result be CreateIteratorFromClosure(closure, "Iterator Helper", // %IteratorHelperPrototype%). // 7. Set result.[[UnderlyingIterator]] to iterated. // 8. Return result. return NewJSIteratorMapHelper(iterated, mapper); } transitioning builtin IteratorMapHelperNext( implicit context: Context)(helper: JSIteratorMapHelper): JSAny { // a. Let counter be 0. // (Done when creating JSIteratorMapHelper.) const fastIteratorResultMap = GetIteratorResultMap(); const underlying = MarkIteratorHelperAsExecuting(helper); const counter = helper.counter; try { // b. Repeat, let next: JSReceiver; try { // i. Let next be ? IteratorStep(iterated). next = IteratorStep(underlying, fastIteratorResultMap) otherwise Done; } label Done { // ii. If next is false, return undefined. MarkIteratorHelperAsExhausted(helper); return AllocateJSIteratorResult(Undefined, True); } // iii. Let value be ? IteratorValue(next). const value = IteratorValue(next, fastIteratorResultMap); try { // iv. Let mapped be Completion( // Call(mapper, undefined, « value, 𝔽(counter) »)). const mapped = Call(context, helper.mapper, Undefined, value, counter); // viii. Set counter to counter + 1. // (Done out of order. Iterator helpers are specified as generators with // yields but we implement them as direct iterators.) helper.counter = counter + 1; // vi. Let completion be Completion(Yield(mapped)). MarkIteratorHelperAsFinishedExecuting(helper, underlying); return AllocateJSIteratorResult(mapped, False); // vii. IfAbruptCloseIterator(completion, iterated). // (Done in IteratorHelperPrototypeReturn.) } catch (e, message) { // v. IfAbruptCloseIterator(mapped, iterated). IteratorCloseOnException(underlying); ReThrowWithMessage(context, e, message); } } catch (e, message) { MarkIteratorHelperAsExhausted(helper); ReThrowWithMessage(context, e, message); } } // --- filter helper macro NewJSIteratorFilterHelper( implicit context: Context)(underlying: IteratorRecord, predicate: Callable): JSIteratorFilterHelper { return new JSIteratorFilterHelper{ map: *NativeContextSlot(ContextSlot::ITERATOR_FILTER_HELPER_MAP_INDEX), properties_or_hash: kEmptyFixedArray, elements: kEmptyFixedArray, underlying: underlying, predicate: predicate, counter: 0 }; } // https://tc39.es/proposal-iterator-helpers/#sec-iteratorprototype.filter transitioning javascript builtin IteratorPrototypeFilter( js-implicit context: NativeContext, receiver: JSAny)( predicate: JSAny): JSIteratorFilterHelper { const methodName: constexpr string = 'Iterator.prototype.filter'; // 1. Let O be the this value. // 2. If O is not an Object, throw a TypeError exception. const o = Cast<JSReceiver>(receiver) otherwise ThrowTypeError(MessageTemplate::kCalledOnNonObject, methodName); // 3. If IsCallable(predicate) is false, throw a TypeError exception. const predicate = Cast<Callable>(predicate) otherwise ThrowCalledNonCallable(methodName); // 4. Let iterated be ? GetIteratorDirect(O). const iterated = GetIteratorDirect(o); // Step 5 implemented in IteratorFilterHelperNext // 6. Let result be CreateIteratorFromClosure(closure, "Iterator Helper", // %IteratorHelperPrototype%). // 7. Set result.[[UnderlyingIterator]] to iterated. // 8. Return result. return NewJSIteratorFilterHelper(iterated, predicate); } transitioning builtin IteratorFilterHelperNext( implicit context: Context)(helper: JSIteratorFilterHelper): JSAny { // a. Let counter be 0. // (Done when creating JSIteratorFilterHelper.) const fastIteratorResultMap = GetIteratorResultMap(); const underlying = MarkIteratorHelperAsExecuting(helper); try { while (true) { const counter = helper.counter; // b. Repeat, let next: JSReceiver; try { // i. Let next be ? IteratorStep(iterated). next = IteratorStep(underlying, fastIteratorResultMap) otherwise Done; } label Done { // ii. If next is false, return undefined. MarkIteratorHelperAsExhausted(helper); return AllocateJSIteratorResult(Undefined, True); } // iii. Let value be ? IteratorValue(next). const value = IteratorValue(next, fastIteratorResultMap); try { // iv. Let selected be Completion( // Call(predicate, undefined, « value, 𝔽(counter) »)). const selected = Call(context, helper.predicate, Undefined, value, counter); // vii. Set counter to counter + 1. // (Done out of order. Iterator helpers are specified as generators with // yields but we implement them as direct iterators.) helper.counter = counter + 1; // vi. If ToBoolean(selected) is true, then if (ToBoolean(selected)) { // 1. Let completion be Completion(Yield(value)). MarkIteratorHelperAsFinishedExecuting(helper, underlying); return AllocateJSIteratorResult(value, False); // 2. IfAbruptCloseIterator(completion, iterated). // (Done in IteratorHelperPrototypeReturn.) } } catch (e, message) { // v. IfAbruptCloseIterator(selected, iterated). IteratorCloseOnException(underlying); ReThrowWithMessage(context, e, message); } } } catch (e, message) { MarkIteratorHelperAsExhausted(helper); ReThrowWithMessage(context, e, message); } unreachable; } // --- take helper macro NewJSIteratorTakeHelper( implicit context: Context)(underlying: IteratorRecord, limit: Number): JSIteratorTakeHelper { return new JSIteratorTakeHelper{ map: *NativeContextSlot(ContextSlot::ITERATOR_TAKE_HELPER_MAP_INDEX), properties_or_hash: kEmptyFixedArray, elements: kEmptyFixedArray, underlying: underlying, remaining: limit }; } // https://tc39.es/proposal-iterator-helpers/#sec-iteratorprototype.take transitioning javascript builtin IteratorPrototypeTake( js-implicit context: NativeContext, receiver: JSAny)( limit: JSAny): JSIteratorTakeHelper { try { const methodName: constexpr string = 'Iterator.prototype.take'; // 1. Let O be the this value. // 2. If O is not an Object, throw a TypeError exception. const o = Cast<JSReceiver>(receiver) otherwise ThrowTypeError(MessageTemplate::kCalledOnNonObject, methodName); // 3. Let numLimit be ? ToNumber(limit). const numLimit = ToNumber_Inline(limit); // 4. If numLimit is NaN, throw a RangeError exception. if (NumberIsNaN(numLimit)) goto RangeError; // 5. Let integerLimit be ! ToIntegerOrInfinity(numLimit). const integerLimit = ToInteger_Inline(numLimit); // 6. If integerLimit < 0, throw a RangeError exception. if (integerLimit < 0) goto RangeError; // 5. Let iterated be ? GetIteratorDirect(O). const iterated = GetIteratorDirect(o); // Step 6 implemented in IteratorTakeHelperNext // 7. Let result be CreateIteratorFromClosure(closure, "Iterator Helper", // %IteratorHelperPrototype%). // 8. Set result.[[UnderlyingIterator]] to iterated. // 9. Return result. return NewJSIteratorTakeHelper(iterated, integerLimit); } label RangeError deferred { ThrowRangeError(MessageTemplate::kMustBePositive, limit); } } transitioning builtin IteratorTakeHelperNext( implicit context: Context)(helper: JSIteratorTakeHelper): JSAny { // a. Let remaining be integerLimit. // (Done when creating JSIteratorTakeHelper.) const fastIteratorResultMap = GetIteratorResultMap(); const underlying = MarkIteratorHelperAsExecuting(helper); const remaining = helper.remaining; try { // b. Repeat, let next: JSReceiver; // i. If remaining is 0, then if (remaining == 0) { // 1. Return ? IteratorClose(iterated, NormalCompletion(undefined)). MarkIteratorHelperAsExhausted(helper); IteratorClose(underlying); return AllocateJSIteratorResult(Undefined, True); } // ii. If remaining is not +∞, then if (!NumberIsSomeInfinity(remaining)) { // 1. Set remaining to remaining - 1. helper.remaining = remaining - 1; } try { // iii. Let next be ? IteratorStep(iterated). next = IteratorStep(underlying, fastIteratorResultMap) otherwise Done; } label Done { // iv. If next is false, return undefined. MarkIteratorHelperAsExhausted(helper); return AllocateJSIteratorResult(Undefined, True); } // v. Let completion be Completion(Yield(? IteratorValue(next))). const value = IteratorValue(next, fastIteratorResultMap); MarkIteratorHelperAsFinishedExecuting(helper, underlying); return AllocateJSIteratorResult(value, False); // vi. IfAbruptCloseIterator(completion, iterated). // (Done in IteratorHelperPrototypeReturn.) } catch (e, message) { MarkIteratorHelperAsExhausted(helper); ReThrowWithMessage(context, e, message); } } // --- drop helper macro NewJSIteratorDropHelper( implicit context: Context)(underlying: IteratorRecord, limit: Number): JSIteratorDropHelper { return new JSIteratorDropHelper{ map: *NativeContextSlot(ContextSlot::ITERATOR_DROP_HELPER_MAP_INDEX), properties_or_hash: kEmptyFixedArray, elements: kEmptyFixedArray, underlying: underlying, remaining: limit }; } // https://tc39.es/proposal-iterator-helpers/#sec-iteratorprototype.drop transitioning javascript builtin IteratorPrototypeDrop( js-implicit context: NativeContext, receiver: JSAny)( limit: JSAny): JSIteratorDropHelper { try { const methodName: constexpr string = 'Iterator.prototype.drop'; // 1. Let O be the this value. // 2. If O is not an Object, throw a TypeError exception. const o = Cast<JSReceiver>(receiver) otherwise ThrowTypeError(MessageTemplate::kCalledOnNonObject, methodName); // 3. Let numLimit be ? ToNumber(limit). const numLimit = ToNumber_Inline(limit); // 4. If numLimit is NaN, throw a RangeError exception. if (NumberIsNaN(numLimit)) goto RangeError; // 5. Let integerLimit be ! ToIntegerOrInfinity(numLimit). const integerLimit = ToInteger_Inline(numLimit); // 6. If integerLimit < 0, throw a RangeError exception. if (integerLimit < 0) goto RangeError; // 5. Let iterated be ? GetIteratorDirect(O). const iterated = GetIteratorDirect(o); // Step 6 implemented in IteratorDropHelperNext // 7. Let result be CreateIteratorFromClosure(closure, "Iterator Helper", // %IteratorHelperPrototype%). // 8. Set result.[[UnderlyingIterator]] to iterated. // 9. Return result. return NewJSIteratorDropHelper(iterated, integerLimit); } label RangeError deferred { ThrowRangeError(MessageTemplate::kMustBePositive, limit); } } transitioning builtin IteratorDropHelperNext( implicit context: Context)(helper: JSIteratorDropHelper): JSAny { // a. Let remaining be integerLimit. // (Done when creating JSIteratorDropHelper.) const fastIteratorResultMap = GetIteratorResultMap(); const underlying = MarkIteratorHelperAsExecuting(helper); let remaining = helper.remaining; let next: JSReceiver; try { // b. Repeat, while remaining > 0, try { while (remaining > 0) { // i. If remaining is not +∞, then if (!NumberIsSomeInfinity(remaining)) { // 1. Set remaining to remaining - 1. remaining = remaining - 1; helper.remaining = remaining; } // ii. Let next be ? IteratorStep(iterated). IteratorStep(underlying, fastIteratorResultMap) otherwise Done; } // c. Repeat, // i. Let next be ? IteratorStep(iterated). next = IteratorStep(underlying, fastIteratorResultMap) otherwise Done; } label Done { // ii. If next is false, return undefined. MarkIteratorHelperAsExhausted(helper); return AllocateJSIteratorResult(Undefined, True); } // iii. Let completion be Completion(Yield(? IteratorValue(next))). const value = IteratorValue(next, fastIteratorResultMap); MarkIteratorHelperAsFinishedExecuting(helper, underlying); return AllocateJSIteratorResult(value, False); // iv. IfAbruptCloseIterator(completion, iterated). // (Done in IteratorHelperPrototypeReturn.) } catch (e, message) { MarkIteratorHelperAsExhausted(helper); ReThrowWithMessage(context, e, message); } } // --- flatMap helper const kFlatMapMethodName: constexpr string = 'Iterator.prototype.flatMap'; macro NewJSIteratorFlatMapHelper( implicit context: Context)(underlying: IteratorRecord, mapper: Callable): JSIteratorFlatMapHelper { return new JSIteratorFlatMapHelper{ map: *NativeContextSlot(ContextSlot::ITERATOR_FLAT_MAP_HELPER_MAP_INDEX), properties_or_hash: kEmptyFixedArray, elements: kEmptyFixedArray, underlying: underlying, mapper: mapper, counter: 0, innerIterator: underlying, innerAlive: False }; } // https://tc39.es/proposal-iterator-helpers/#sec-iteratorprototype.flatmap transitioning javascript builtin IteratorPrototypeFlatMap( js-implicit context: NativeContext, receiver: JSAny)( mapper: JSAny): JSIteratorFlatMapHelper { // 1. Let O be the this value. // 2. If O is not an Object, throw a TypeError exception. const o = Cast<JSReceiver>(receiver) otherwise ThrowTypeError( MessageTemplate::kCalledOnNonObject, kFlatMapMethodName); // 3. If IsCallable(mapper) is false, throw a TypeError exception. const mapper = Cast<Callable>(mapper) otherwise ThrowTypeError( MessageTemplate::kCalledNonCallable, kFlatMapMethodName); // 4. Let iterated be ? GetIteratorDirect(O). const iterated = GetIteratorDirect(o); // Step 5 implemented in IteratorFlatMapHelperNext // 6. Let result be CreateIteratorFromClosure(closure, "Iterator Helper", // %IteratorHelperPrototype%). // 7. Set result.[[UnderlyingIterator]] to iterated. // 8. Return result. return NewJSIteratorFlatMapHelper(iterated, mapper); } transitioning builtin IteratorFlatMapHelperNext( implicit context: Context)(helper: JSIteratorFlatMapHelper): JSAny { // a. Let counter be 0. // (Done when creating JSIteratorFlatMapHelper.) const fastIteratorResultMap = GetIteratorResultMap(); const underlying = MarkIteratorHelperAsExecuting(helper); try { while (true) { const counter = helper.counter; let innerIterator = helper.innerIterator; // b. Repeat, if (helper.innerAlive == False) { let next: JSReceiver; try { // i. Let next be ? IteratorStep(iterated). next = IteratorStep(underlying, fastIteratorResultMap) otherwise Done; } label Done { // ii. If next is false, return undefined. MarkIteratorHelperAsExhausted(helper); return AllocateJSIteratorResult(Undefined, True); } // iii. Let value be ? IteratorValue(next). const value = IteratorValue(next, fastIteratorResultMap); try { // iv. Let mapped be Completion( // Call(mapper, undefined, « value, 𝔽(counter) »)). const mapped = Call(context, helper.mapper, Undefined, value, counter); const mappedIter = Cast<JSReceiver>(mapped) otherwise ThrowTypeError( MessageTemplate::kCalledOnNonObject, kFlatMapMethodName); // vi. Let innerIterator be Completion(GetIteratorFlattenable(mapped, // reject-strings)). innerIterator = GetIteratorFlattenable(mappedIter); helper.innerIterator = innerIterator; // viii. Let innerAlive be true. helper.innerAlive = True; } catch (e, message) { // v. IfAbruptCloseIterator(mapped, iterated) IteratorCloseOnException(underlying); ReThrowWithMessage(context, e, message); } // x. Set counter to counter + 1. helper.counter = counter + 1; } // ix. Repeat, while innerAlive is true, try { // 1. Let innerNext be Completion(IteratorStep(innerIterator)). let innerNext: JSReceiver; innerNext = IteratorStep(innerIterator, fastIteratorResultMap) otherwise Done; // 4. Else, // a. Let innerValue be Completion(IteratorValue(innerNext)). const innerValue = IteratorValue(innerNext, fastIteratorResultMap); // c. Let completion be Completion(Yield(innerValue)). MarkIteratorHelperAsFinishedExecuting(helper, underlying); return AllocateJSIteratorResult(innerValue, False); // d. If completion is an abrupt completion, then // i. Let backupCompletion be Completion(IteratorClose(innerIterator, // completion)). // ii. IfAbruptCloseIterator(backupCompletion, iterated). // iii. Return ? IteratorClose(completion, iterated). // Done in IteratorHelperPrototypeReturn. } catch (e, message) { // 2. IfAbruptCloseIterator(innerNext, iterated) IteratorCloseOnException(underlying); ReThrowWithMessage(context, e, message); } label Done { // 3. If innerNext is false, then // a. Set innerAlive to false. helper.innerAlive = False; } } } catch (e, message) { MarkIteratorHelperAsExhausted(helper); ReThrowWithMessage(context, e, message); } unreachable; } // --- reduce helper // https://tc39.es/proposal-iterator-helpers/#sec-iteratorprototype.reduce transitioning javascript builtin IteratorPrototypeReduce( js-implicit context: NativeContext, receiver: JSAny)(...arguments): JSAny { const methodName: constexpr string = 'Iterator.prototype.reduce'; // 1. Let O be the this value. // 2. If O is not an Object, throw a TypeError exception. const o = Cast<JSReceiver>(receiver) otherwise ThrowTypeError(MessageTemplate::kCalledOnNonObject, methodName); // 3. If IsCallable(reducer) is false, throw a TypeError exception. const reducer = Cast<Callable>(arguments[0]) otherwise ThrowCalledNonCallable(methodName); // 4. Let iterated be ? GetIteratorDirect(O). const iterated = GetIteratorDirect(o); const fastIteratorResultMap = GetIteratorResultMap(); let next: JSReceiver; let accumulator: JSAny; let counter: Number; // 5. If initialValue is not present, then if (arguments.length == 1) { // a. Let next be ? IteratorStep(iterated). // b. If next is false, throw a TypeError exception. next = IteratorStep(iterated, fastIteratorResultMap) otherwise ThrowTypeError( MessageTemplate::kIteratorReduceNoInitial, methodName); // c. Let accumulator be ? IteratorValue(next). accumulator = IteratorValue(next, fastIteratorResultMap); // d. Let counter be 1. counter = 1; } else { // 6. Else, // a. Let accumulator be initialValue. accumulator = arguments[1]; // b. Let counter be 0. counter = 0; } // 7. Repeat, while (true) { try { // a. Let next be ? IteratorStep(iterated). next = IteratorStep(iterated, fastIteratorResultMap) otherwise Done; } label Done { // b. If next is false, return accumulator. return accumulator; } // c. Let value be ? IteratorValue(next). const value = IteratorValue(next, fastIteratorResultMap); try { // d. Let result be Completion(Call(reducer, undefined, « accumulator, // value, 𝔽(counter) »)). const result = Call(context, reducer, Undefined, accumulator, value, counter); // f. Set accumulator to result.[[Value]]. accumulator = result; // g. Set counter to counter + 1. counter = counter + 1; } catch (e, message) { // e. IfAbruptCloseIterator(result, iterated). IteratorCloseOnException(iterated); ReThrowWithMessage(context, e, message); } } unreachable; } // --- toArray helper // https://tc39.es/proposal-iterator-helpers/#sec-iteratorprototype.toarray transitioning javascript builtin IteratorPrototypeToArray( js-implicit context: NativeContext, receiver: JSAny)(): JSAny { const methodName: constexpr string = 'Iterator.prototype.toArray'; // 1. Let O be the this value. // 2. If O is not an Object, throw a TypeError exception. const o = Cast<JSReceiver>(receiver) otherwise ThrowTypeError(MessageTemplate::kCalledOnNonObject, methodName); // 3. Let iterated be ? GetIteratorDirect(O). const iterated = GetIteratorDirect(o); // 4. Let items be a new empty List. let items = growable_fixed_array::NewGrowableFixedArray(); const fastIteratorResultMap = GetIteratorResultMap(); let next: JSReceiver; // 5. Repeat, while (true) { try { // a. Let next be ? IteratorStep(iterated). next = IteratorStep(iterated, fastIteratorResultMap) otherwise Done; } label Done { // b. If next is false, return CreateArrayFromList(items). return items.ToJSArray(); } // c. Let value be ? IteratorValue(next). const value = IteratorValue(next, fastIteratorResultMap); // d. Append value to items. items.Push(value); } unreachable; } // --- forEach helper // https://tc39.es/proposal-iterator-helpers/#sec-iteratorprototype.foreach transitioning javascript builtin IteratorPrototypeForEach( js-implicit context: NativeContext, receiver: JSAny)(fn: JSAny): JSAny { const methodName: constexpr string = 'Iterator.prototype.forEach'; // 1. Let O be the this value. // 2. If O is not an Object, throw a TypeError exception. const o = Cast<JSReceiver>(receiver) otherwise ThrowTypeError(MessageTemplate::kCalledOnNonObject, methodName); // 3. If IsCallable(fn) is false, throw a TypeError exception. const fn = Cast<Callable>(fn) otherwise ThrowCalledNonCallable(methodName); // 4. Let iterated be ? GetIteratorDirect(O). const iterated = GetIteratorDirect(o); // 5. Let counter be 0. let counter: Number = 0; const fastIteratorResultMap = GetIteratorResultMap(); // 5. Repeat, while (true) { let next: JSReceiver; try { // a. Let next be ? IteratorStep(iterated). next = IteratorStep(iterated, fastIteratorResultMap) otherwise Done; } label Done { // b. If next is false, return undefined. return Undefined; } // c. Let value be ? IteratorValue(next). const value = IteratorValue(next, fastIteratorResultMap); try { // d. Let result be Completion(Call(fn, undefined, « value, 𝔽(counter) // »)). Call(context, fn, Undefined, value, counter); // f. Set counter to counter + 1. counter = counter + 1; } catch (e, message) { // e. IfAbruptCloseIterator(result, iterated). IteratorCloseOnException(iterated); ReThrowWithMessage(context, e, message); } } unreachable; } // --- some helper // https://tc39.es/proposal-iterator-helpers/#sec-iteratorprototype.some transitioning javascript builtin IteratorPrototypeSome( js-implicit context: NativeContext, receiver: JSAny)( predicate: JSAny): JSAny { const methodName: constexpr string = 'Iterator.prototype.some'; // 1. Let O be the this value. // 2. If O is not an Object, throw a TypeError exception. const o = Cast<JSReceiver>(receiver) otherwise ThrowTypeError(MessageTemplate::kCalledOnNonObject, methodName); // 3. If IsCallable(predicate) is false, throw a TypeError exception. const predicate = Cast<Callable>(predicate) otherwise ThrowCalledNonCallable(methodName); // 4. Let iterated be ? GetIteratorDirect(O). const iterated = GetIteratorDirect(o); // 5. Let counter be 0. let counter: Number = 0; const fastIteratorResultMap = GetIteratorResultMap(); // 5. Repeat, while (true) { let next: JSReceiver; try { // a. Let next be ? IteratorStep(iterated). next = IteratorStep(iterated, fastIteratorResultMap) otherwise Done; } label Done { // b. If next is false, return false. return False; } // c. Let value be ? IteratorValue(next). const value = IteratorValue(next, fastIteratorResultMap); let result: JSAny; try { // d. Let result be Completion(Call(predicate, undefined, « value, // 𝔽(counter) »)). result = Call(context, predicate, Undefined, value, counter); } catch (e, message) { // e. IfAbruptCloseIterator(result, iterated). IteratorCloseOnException(iterated); ReThrowWithMessage(context, e, message); } // f. If ToBoolean(result) is true, return ? IteratorClose(iterated, // NormalCompletion(true)). if (ToBoolean(result) == true) { IteratorClose(iterated); return True; } // g. Set counter to counter + 1. counter = counter + 1; } unreachable; } // --- every helper // https://tc39.es/proposal-iterator-helpers/#sec-iteratorprototype.every transitioning javascript builtin IteratorPrototypeEvery( js-implicit context: NativeContext, receiver: JSAny)( predicate: JSAny): JSAny { const methodName: constexpr string = 'Iterator.prototype.every'; // 1. Let O be the this value. // 2. If O is not an Object, throw a TypeError exception. const o = Cast<JSReceiver>(receiver) otherwise ThrowTypeError(MessageTemplate::kCalledOnNonObject, methodName); // 3. If IsCallable(predicate) is false, throw a TypeError exception. const predicate = Cast<Callable>(predicate) otherwise ThrowCalledNonCallable(methodName); // 4. Let iterated be ? GetIteratorDirect(O). const iterated = GetIteratorDirect(o); // 5. Let counter be 0. let counter: Number = 0; const fastIteratorResultMap = GetIteratorResultMap(); // 5. Repeat, while (true) { let next: JSReceiver; try { // a. Let next be ? IteratorStep(iterated). next = IteratorStep(iterated, fastIteratorResultMap) otherwise Done; } label Done { // b. If next is false, return true. return True; } // c. Let value be ? IteratorValue(next). const value = IteratorValue(next, fastIteratorResultMap); let result: JSAny; try { // d. Let result be Completion(Call(predicate, undefined, « value, // 𝔽(counter) »)). result = Call(context, predicate, Undefined, value, counter); } catch (e, message) { // e. IfAbruptCloseIterator(result, iterated). IteratorCloseOnException(iterated); ReThrowWithMessage(context, e, message); } // f. If ToBoolean(result) is false, return ? IteratorClose(iterated, // NormalCompletion(false)). if (ToBoolean(result) == false) { IteratorClose(iterated); return False; } // g. Set counter to counter + 1. counter = counter + 1; } unreachable; } // --- find helper // https://tc39.es/proposal-iterator-helpers/#sec-iteratorprototype.find transitioning javascript builtin IteratorPrototypeFind( js-implicit context: NativeContext, receiver: JSAny)( predicate: JSAny): JSAny { const methodName: constexpr string = 'Iterator.prototype.find'; // 1. Let O be the this value. // 2. If O is not an Object, throw a TypeError exception. const o = Cast<JSReceiver>(receiver) otherwise ThrowTypeError(MessageTemplate::kCalledOnNonObject, methodName); // 3. If IsCallable(predicate) is false, throw a TypeError exception. const predicate = Cast<Callable>(predicate) otherwise ThrowCalledNonCallable(methodName); // 4. Let iterated be ? GetIteratorDirect(O). const iterated = GetIteratorDirect(o); // 5. Let counter be 0. let counter: Number = 0; const fastIteratorResultMap = GetIteratorResultMap(); // 5. Repeat, while (true) { let next: JSReceiver; try { // a. Let next be ? IteratorStep(iterated). next = IteratorStep(iterated, fastIteratorResultMap) otherwise Done; } label Done { // b. If next is false, return undefined. return Undefined; } // c. Let value be ? IteratorValue(next). const value = IteratorValue(next, fastIteratorResultMap); let result: JSAny; try { // d. Let result be Completion(Call(predicate, undefined, « value, // 𝔽(counter) »)). result = Call(context, predicate, Undefined, value, counter); } catch (e, message) { // e. IfAbruptCloseIterator(result, iterated). IteratorCloseOnException(iterated); ReThrowWithMessage(context, e, message); } // f. If ToBoolean(result) is true, return ? IteratorClose(iterated, // NormalCompletion(value)). if (ToBoolean(result) == true) { IteratorClose(iterated); return value; } // g. Set counter to counter + 1. counter = counter + 1; } unreachable; } } // namespace iterator