%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /home/vacivi36/vittasync.vacivitta.com.br/vittasync/node/deps/v8/src/builtins/
Upload File :
Create Path :
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

Zerion Mini Shell 1.0