function thenPromiseFulfilledOrRejected()

in jones-promises/lib/Promise.js [50:130]


function thenPromiseFulfilledOrRejected(original_promise, 
                                        fulfilled_or_rejected_callback, 
                                        new_promise, result, isRejected) {
  var new_result;
  try {
    if (fulfilled_or_rejected_callback) {
      new_result = fulfilled_or_rejected_callback.call(undefined, result);
    } else {
      if (isRejected) {
        // 2.2.7.4 If onRejected is not a function and promise1 is rejected, promise2 must be rejected with the same reason.
        new_promise.reject(result);
      } else {
        // 2.2.7.3 If onFulfilled is not a function and promise1 is fulfilled, promise2 must be fulfilled with the same value.
        new_promise.fulfill(result);
      }
      return;
    }
    var new_result_type = typeof new_result;
    if ((new_result_type === 'object' && new_result_type != null) | new_result_type === 'function') { 
      // 2.3.3 if result is an object or function
      // 2.3 The Promise Resolution Procedure
      // 2.3.1 If promise and x refer to the same object, reject promise with a TypeError as the reason.
      if (new_result === original_promise) {
        throw new Error('TypeError: Promise Resolution Procedure 2.3.1');
      }
      // 2.3.2 If x is a promise, adopt its state; but we don't care since it's also a thenable
      var then;
      try {
        then = new_result.then;
      } catch (thenE) {
        // 2.2.3.2 If retrieving the property x.then results in a thrown exception e, 
        // reject promise with e as the reason.
        new_promise.reject(thenE);
        return;
      }
      if (typeof then === 'function') {
        // 2.3.3.3 If then is a function, call it with x as this, first argument resolvePromise, 
        // and second argument rejectPromise
        // 2.3.3.3.3 If both resolvePromise and rejectPromise are called, 
        // or multiple calls to the same argument are made, the first call takes precedence, 
        // and any further calls are ignored.
        try {
          then.call(new_result,
            // 2.3.3.3.1 If/when resolvePromise is called with a value y, run [[Resolve]](promise, y).
            function(result) {
            if(udebug.is_detail()) { udebug.log(original_promise.name, 'thenPromiseFulfilledOrRejected deferred fulfill callback', new_result); }
              if (!new_promise.resolved) {
                new_promise.fulfill(result);
              }
            },
            // 2.3.3.3.2 If/when rejectPromise is called with a reason r, reject promise with r.
            function(err) {
              if(udebug.is_detail()) { udebug.log(original_promise.name, 'thenPromiseFulfilledOrRejected deferred reject callback', new_result); }
              if (!new_promise.resolved) {
                new_promise.reject(err);
              }
            }
          );
        } catch (callE) {
          // 2.3.3.3.4 If calling then throws an exception e,
          // 2.3.3.3.4.1 If resolvePromise or rejectPromise have been called, ignore it.
          if (!new_promise.resolved) {
            // 2.3.3.3.4.2 Otherwise, reject promise with e as the reason.
            new_promise.reject(callE);
          }
        }
      } else {
        // 2.3.3.4 If then is not a function, fulfill promise with x.
        new_promise.fulfill(new_result);
      }
    } else {
      // 2.3.4 If x is not an object or function, fulfill promise with x.
      new_promise.fulfill(new_result);
    }
  } catch (fulfillE) {
    // 2.2.7.2 If either onFulfilled or onRejected throws an exception e,
    // promise2 must be rejected with e as the reason.
    new_promise.reject(fulfillE);
  }
  
};