// Copyright 2019 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.

#include 'src/builtins/builtins-promise.h'
#include 'src/builtins/builtins-promise-gen.h'

namespace promise {
const kPromiseBuiltinsPromiseContextLength: constexpr int31
    generates 'PromiseBuiltins::kPromiseContextLength';

// Creates the context used by all Promise.all resolve element closures,
// together with the values array. Since all closures for a single Promise.all
// call use the same context, we need to store the indices for the individual
// closures somewhere else (we put them into the identity hash field of the
// closures), and we also need to have a separate marker for when the closure
// was called already (we slap the native context onto the closure in that
// case to mark it's done).
macro CreatePromiseAllResolveElementContext(implicit context: Context)(
    capability: PromiseCapability,
    nativeContext: NativeContext): PromiseAllResolveElementContext {
  const resolveContext = %RawDownCast<
      PromiseAllResolveElementContext>(AllocateSyntheticFunctionContext(
      nativeContext,
      PromiseAllResolveElementContextSlots::kPromiseAllResolveElementLength));
  InitContextSlot(
      resolveContext,
      PromiseAllResolveElementContextSlots::
          kPromiseAllResolveElementRemainingSlot,
      1);
  InitContextSlot(
      resolveContext,
      PromiseAllResolveElementContextSlots::
          kPromiseAllResolveElementCapabilitySlot,
      capability);
  InitContextSlot(
      resolveContext,
      PromiseAllResolveElementContextSlots::kPromiseAllResolveElementValuesSlot,
      kEmptyFixedArray);
  return resolveContext;
}

macro CreatePromiseAllResolveElementFunction(implicit context: Context)(
    resolveElementContext: PromiseAllResolveElementContext, index: Smi,
    nativeContext: NativeContext,
    resolveFunction: SharedFunctionInfo): JSFunction {
  assert(index > 0);
  assert(index < kPropertyArrayHashFieldMax);

  const map = *ContextSlot(
      nativeContext, ContextSlot::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
  const resolve = AllocateFunctionWithMapAndContext(
      map, resolveFunction, resolveElementContext);

  assert(kPropertyArrayNoHashSentinel == 0);
  resolve.properties_or_hash = index;
  return resolve;
}

@export
macro CreatePromiseResolvingFunctionsContext(implicit context: Context)(
    promise: JSPromise, debugEvent: Boolean, nativeContext: NativeContext):
    PromiseResolvingFunctionContext {
  const resolveContext = %RawDownCast<PromiseResolvingFunctionContext>(
      AllocateSyntheticFunctionContext(
          nativeContext,
          PromiseResolvingFunctionContextSlot::kPromiseContextLength));
  InitContextSlot(
      resolveContext, PromiseResolvingFunctionContextSlot::kPromiseSlot,
      promise);
  InitContextSlot(
      resolveContext, PromiseResolvingFunctionContextSlot::kAlreadyResolvedSlot,
      False);
  InitContextSlot(
      resolveContext, PromiseResolvingFunctionContextSlot::kDebugEventSlot,
      debugEvent);
  static_assert(
      PromiseResolvingFunctionContextSlot::kPromiseContextLength ==
      ContextSlot::MIN_CONTEXT_SLOTS + 3);
  return resolveContext;
}

macro IsPromiseThenLookupChainIntact(implicit context: Context)(
    nativeContext: NativeContext, receiverMap: Map): bool {
  if (IsForceSlowPath()) return false;
  if (!IsJSPromiseMap(receiverMap)) return false;
  if (receiverMap.prototype != *NativeContextSlot(
          nativeContext, ContextSlot::PROMISE_PROTOTYPE_INDEX)) {
    return false;
  }
  return !IsPromiseThenProtectorCellInvalid();
}

struct PromiseAllResolveElementFunctor {
  macro Call(implicit context: Context)(
      resolveElementContext: PromiseAllResolveElementContext,
      nativeContext: NativeContext, index: Smi,
      _capability: PromiseCapability): Callable {
    return CreatePromiseAllResolveElementFunction(
        resolveElementContext, index, nativeContext,
        PromiseAllResolveElementSharedFunConstant());
  }
}

struct PromiseAllRejectElementFunctor {
  macro Call(implicit context: Context)(
      _resolveElementContext: PromiseAllResolveElementContext,
      _nativeContext: NativeContext, _index: Smi,
      capability: PromiseCapability): Callable {
    return UnsafeCast<Callable>(capability.reject);
  }
}

struct PromiseAllSettledResolveElementFunctor {
  macro Call(implicit context: Context)(
      resolveElementContext: PromiseAllResolveElementContext,
      nativeContext: NativeContext, index: Smi,
      _capability: PromiseCapability): Callable {
    return CreatePromiseAllResolveElementFunction(
        resolveElementContext, index, nativeContext,
        PromiseAllSettledResolveElementSharedFunConstant());
  }
}

struct PromiseAllSettledRejectElementFunctor {
  macro Call(implicit context: Context)(
      resolveElementContext: PromiseAllResolveElementContext,
      nativeContext: NativeContext, index: Smi,
      _capability: PromiseCapability): Callable {
    return CreatePromiseAllResolveElementFunction(
        resolveElementContext, index, nativeContext,
        PromiseAllSettledRejectElementSharedFunConstant());
  }
}

transitioning macro PerformPromiseAll<F1: type, F2: type>(
    implicit context: Context)(
    nativeContext: NativeContext, iter: iterator::IteratorRecord,
    constructor: Constructor, capability: PromiseCapability,
    promiseResolveFunction: JSAny, createResolveElementFunctor: F1,
    createRejectElementFunctor: F2): JSAny labels
Reject(Object) {
  const promise = capability.promise;
  const resolve = capability.resolve;
  const reject = capability.reject;

  // For catch prediction, don't treat the .then calls as handling it;
  // instead, recurse outwards.
  if (IsDebugActive()) deferred {
      SetPropertyStrict(context, reject, kPromiseForwardingHandlerSymbol, True);
    }

  const resolveElementContext =
      CreatePromiseAllResolveElementContext(capability, nativeContext);

  let index: Smi = 1;

  try {
    const fastIteratorResultMap = *NativeContextSlot(
        nativeContext, ContextSlot::ITERATOR_RESULT_MAP_INDEX);
    while (true) {
      let nextValue: JSAny;
      try {
        // Let next be IteratorStep(iteratorRecord.[[Iterator]]).
        // If next is an abrupt completion, set iteratorRecord.[[Done]] to
        // true. ReturnIfAbrupt(next).
        const next: JSReceiver = iterator::IteratorStep(
            iter, fastIteratorResultMap) otherwise goto Done;

        // Let nextValue be IteratorValue(next).
        // If nextValue is an abrupt completion, set iteratorRecord.[[Done]]
        // to true.
        // ReturnIfAbrupt(nextValue).
        nextValue = iterator::IteratorValue(next, fastIteratorResultMap);
      } catch (e) {
        goto Reject(e);
      }

      // Check if we reached the limit.
      if (index == kPropertyArrayHashFieldMax) {
        // If there are too many elements (currently more than 2**21-1),
        // raise a RangeError here (which is caught below and turned into
        // a rejection of the resulting promise). We could gracefully handle
        // this case as well and support more than this number of elements
        // by going to a separate function and pass the larger indices via a
        // separate context, but it doesn't seem likely that we need this,
        // and it's unclear how the rest of the system deals with 2**21 live
        // Promises anyway.
        ThrowRangeError(
            MessageTemplate::kTooManyElementsInPromiseCombinator, 'all');
      }

      // Set remainingElementsCount.[[Value]] to
      //     remainingElementsCount.[[Value]] + 1.
      *ContextSlot(
          resolveElementContext,
          PromiseAllResolveElementContextSlots::
              kPromiseAllResolveElementRemainingSlot) += 1;

      // Let resolveElement be CreateBuiltinFunction(steps,
      //                                             « [[AlreadyCalled]],
      //                                               [[Index]],
      //                                               [[Values]],
      //                                               [[Capability]],
      //                                               [[RemainingElements]]
      //                                               »).
      // Set resolveElement.[[AlreadyCalled]] to a Record { [[Value]]: false
      // }. Set resolveElement.[[Index]] to index. Set
      // resolveElement.[[Values]] to values. Set
      // resolveElement.[[Capability]] to resultCapability. Set
      // resolveElement.[[RemainingElements]] to remainingElementsCount.
      const resolveElementFun = createResolveElementFunctor.Call(
          resolveElementContext, nativeContext, index, capability);
      const rejectElementFun = createRejectElementFunctor.Call(
          resolveElementContext, nativeContext, index, capability);

      // We can skip the "then" lookup on the result of the "resolve" call and
      // immediately chain the continuation onto the {next_value} if:
      //
      //   (a) The {constructor} is the intrinsic %Promise% function, and
      //       looking up "resolve" on {constructor} yields the initial
      //       Promise.resolve() builtin, and
      //   (b) the promise @@species protector cell is valid, meaning that
      //       no one messed with the Symbol.species property on any
      //       intrinsic promise or on the Promise.prototype, and
      //   (c) the {next_value} is a JSPromise whose [[Prototype]] field
      //       contains the intrinsic %PromisePrototype%, and
      //   (d) we're not running with async_hooks or DevTools enabled.
      //
      // In that case we also don't need to allocate a chained promise for
      // the PromiseReaction (aka we can pass undefined to
      // PerformPromiseThen), since this is only necessary for DevTools and
      // PromiseHooks.
      if (promiseResolveFunction != Undefined ||
          IsPromiseHookEnabledOrDebugIsActiveOrHasAsyncEventDelegate() ||
          IsPromiseSpeciesProtectorCellInvalid() || Is<Smi>(nextValue) ||
          !IsPromiseThenLookupChainIntact(
              nativeContext, UnsafeCast<HeapObject>(nextValue).map)) {
        // Let nextPromise be ? Call(constructor, _promiseResolve_, «
        // nextValue »).
        const nextPromise =
            CallResolve(constructor, promiseResolveFunction, nextValue);

        // Perform ? Invoke(nextPromise, "then", « resolveElement,
        //                  resultCapability.[[Reject]] »).
        const then = GetProperty(nextPromise, kThenString);
        const thenResult = Call(
            nativeContext, then, nextPromise, resolveElementFun,
            rejectElementFun);

        // For catch prediction, mark that rejections here are
        // semantically handled by the combined Promise.
        if (IsDebugActive() && Is<JSPromise>(thenResult)) deferred {
            SetPropertyStrict(
                context, thenResult, kPromiseHandledBySymbol, promise);
          }
      } else {
        PerformPromiseThenImpl(
            UnsafeCast<JSPromise>(nextValue), resolveElementFun,
            rejectElementFun, Undefined);
      }

      // Set index to index + 1.
      index += 1;
    }
  } catch (e) deferred {
    iterator::IteratorCloseOnException(iter);
    goto Reject(e);
  } label Done {}

  // Set iteratorRecord.[[Done]] to true.
  // Set remainingElementsCount.[[Value]] to
  //    remainingElementsCount.[[Value]] - 1.
  const remainingElementsCount = -- *ContextSlot(
      resolveElementContext,
      PromiseAllResolveElementContextSlots::
          kPromiseAllResolveElementRemainingSlot);

  check(remainingElementsCount >= 0);

  if (remainingElementsCount > 0) {
    // Pre-allocate the backing store for the {values} to the desired
    // capacity. We may already have elements in "values" - this happens
    // when the Thenable calls the resolve callback immediately.
    const valuesRef:&FixedArray = ContextSlot(
        resolveElementContext,
        PromiseAllResolveElementContextSlots::
            kPromiseAllResolveElementValuesSlot);
    const values = *valuesRef;
    // 'index' is a 1-based index and incremented after every Promise. Later we
    // use 'values' as a 0-based array, so capacity 'index - 1' is enough.
    const newCapacity = SmiUntag(index) - 1;

    const oldCapacity = values.length_intptr;
    if (oldCapacity < newCapacity) {
      *valuesRef = ExtractFixedArray(values, 0, oldCapacity, newCapacity);
    }
  } else
    deferred {
      // If remainingElementsCount.[[Value]] is 0, then
      //     Let valuesArray be CreateArrayFromList(values).
      //     Perform ? Call(resultCapability.[[Resolve]], undefined,
      //                    « valuesArray »).

      const values: FixedArray = *ContextSlot(
          resolveElementContext,
          PromiseAllResolveElementContextSlots::
              kPromiseAllResolveElementValuesSlot);
      const arrayMap =
          *NativeContextSlot(
          nativeContext, ContextSlot::JS_ARRAY_PACKED_ELEMENTS_MAP_INDEX);
      const valuesArray = NewJSArray(arrayMap, values);
      Call(nativeContext, UnsafeCast<JSAny>(resolve), Undefined, valuesArray);
    }

  // Return resultCapability.[[Promise]].
  return promise;
}

transitioning macro GeneratePromiseAll<F1: type, F2: type>(
    implicit context: Context)(
    receiver: JSAny, iterable: JSAny, createResolveElementFunctor: F1,
    createRejectElementFunctor: F2): JSAny {
  const nativeContext = LoadNativeContext(context);
  // Let C be the this value.
  // If Type(C) is not Object, throw a TypeError exception.
  const receiver = Cast<JSReceiver>(receiver)
      otherwise ThrowTypeError(MessageTemplate::kCalledOnNonObject, 'Promise.all');

  // Let promiseCapability be ? NewPromiseCapability(C).
  // Don't fire debugEvent so that forwarding the rejection through all does
  // not trigger redundant ExceptionEvents
  const capability = NewPromiseCapability(receiver, False);

  // NewPromiseCapability guarantees that receiver is Constructor.
  assert(Is<Constructor>(receiver));
  const constructor = UnsafeCast<Constructor>(receiver);

  try {
    // Let promiseResolve be GetPromiseResolve(C).
    // IfAbruptRejectPromise(promiseResolve, promiseCapability).
    const promiseResolveFunction =
        GetPromiseResolve(nativeContext, constructor);

    // Let iterator be GetIterator(iterable).
    // IfAbruptRejectPromise(iterator, promiseCapability).
    let i = iterator::GetIterator(iterable);

    // Let result be PerformPromiseAll(iteratorRecord, C,
    // promiseCapability). If result is an abrupt completion, then
    //   If iteratorRecord.[[Done]] is false, let result be
    //       IteratorClose(iterator, result).
    //    IfAbruptRejectPromise(result, promiseCapability).
    return PerformPromiseAll(
        nativeContext, i, constructor, capability, promiseResolveFunction,
        createResolveElementFunctor, createRejectElementFunctor)
        otherwise Reject;
  } catch (e) deferred {
    goto Reject(e);
  } label Reject(e: Object) deferred {
    // Exception must be bound to a JS value.
    const e = UnsafeCast<JSAny>(e);
    const reject = UnsafeCast<JSAny>(capability.reject);
    Call(context, reject, Undefined, e);
    return capability.promise;
  }
}

// ES#sec-promise.all
transitioning javascript builtin PromiseAll(
    js-implicit context: Context, receiver: JSAny)(iterable: JSAny): JSAny {
  return GeneratePromiseAll(
      receiver, iterable, PromiseAllResolveElementFunctor{},
      PromiseAllRejectElementFunctor{});
}

// ES#sec-promise.allsettled
// Promise.allSettled ( iterable )
transitioning javascript builtin PromiseAllSettled(
    js-implicit context: Context, receiver: JSAny)(iterable: JSAny): JSAny {
  return GeneratePromiseAll(
      receiver, iterable, PromiseAllSettledResolveElementFunctor{},
      PromiseAllSettledRejectElementFunctor{});
}

extern macro PromiseAllResolveElementSharedFunConstant(): SharedFunctionInfo;
extern macro PromiseAllSettledRejectElementSharedFunConstant():
    SharedFunctionInfo;
extern macro PromiseAllSettledResolveElementSharedFunConstant():
    SharedFunctionInfo;
}
