ES#sec-promise.prototype.then Promise.prototype.then ( onFulfilled, onRejected ) Multi-unwrapped chaining with thenable coercion.
function PromiseThen(onResolve, onReject) {
  var status = GET_PRIVATE(this, promiseStateSymbol);
  if (IS_UNDEFINED(status)) {
    throw MakeTypeError(kNotAPromise, this);
  }

  var constructor = SpeciesConstructor(this, GlobalPromise);
  onResolve = IS_CALLABLE(onResolve) ? onResolve : PromiseIdResolveHandler;
  onReject = IS_CALLABLE(onReject) ? onReject : PromiseIdRejectHandler;
  var deferred = NewPromiseCapability(constructor);
  switch (status) {
    case kPending:
      PromiseAttachCallbacks(this, deferred, onResolve, onReject);
      break;
    case kFulfilled:
      PromiseEnqueue(GET_PRIVATE(this, promiseResultSymbol),
                     onResolve, deferred, kFulfilled);
      break;
    case kRejected:
      if (!HAS_DEFINED_PRIVATE(this, promiseHasHandlerSymbol)) {
        // Promise has already been rejected, but had no handler.
        // Revoke previously triggered reject event.
        %PromiseRevokeReject(this);
      }
      PromiseEnqueue(GET_PRIVATE(this, promiseResultSymbol),
                     onReject, deferred, kRejected);
      break;
  }
  // Mark this promise as having handler.
  SET_PRIVATE(this, promiseHasHandlerSymbol, true);
  return deferred.promise;
}