text: /** @license MIT License (c) copyright 2010-2014 original author or authors */
  
  /**
   * Promises/A+ and when() implementation
   * when is part of the cujoJS family of libraries (http://cujojs.com/)
   * @author Brian Cavalier
   * @author John Hann
   */
  (function (define) {
    'use strict';
    define(function (require) {
  
      var timed = require('./lib/decorators/timed');
      var array = require('./lib/decorators/array');
      var flow = require('./lib/decorators/flow');
      var fold = require('./lib/decorators/fold');
      var inspect = require('./lib/decorators/inspect');
      var generate = require('./lib/decorators/iterate');
      var progress = require('./lib/decorators/progress');
      var withThis = require('./lib/decorators/with');
      var unhandledRejection = require('./lib/decorators/unhandledRejection');
      var TimeoutError = require('./lib/TimeoutError');
  
      var Promise = [array, flow, fold, generate, progress,
        inspect, withThis, timed, unhandledRejection]
        .reduce(function (Promise, feature) {
          return feature(Promise);
        }, require('./lib/Promise'));
  
      var apply = require('./lib/apply')(Promise);
  
      // Public API
  
      when.promise = promise;              // Create a pending promise
      when.resolve = Promise.resolve;      // Create a resolved promise
      when.reject = Promise.reject;       // Create a rejected promise
  
      when.lift = lift;                 // lift a function to return promises
      when['try'] = attempt;              // call a function and return a promise
      when.attempt = attempt;              // alias for when.try
  
      when.iterate = Promise.iterate;      // DEPRECATED (use cujojs/most streams) Generate a stream of promises
      when.unfold = Promise.unfold;       // DEPRECATED (use cujojs/most streams) Generate a stream of promises
  
      when.join = join;                 // Join 2 or more promises
  
      when.all = all;                  // Resolve a list of promises
      when.settle = settle;               // Settle a list of promises
  
      when.any = lift(Promise.any);    // One-winner race
      when.some = lift(Promise.some);   // Multi-winner race
      when.race = lift(Promise.race);   // First-to-settle race
  
      when.map = map;                  // Array.map() for promises
      when.filter = filter;               // Array.filter() for promises
      when.reduce = lift(Promise.reduce);       // Array.reduce() for promises
      when.reduceRight = lift(Promise.reduceRight);  // Array.reduceRight() for promises
  
      when.isPromiseLike = isPromiseLike;      // Is something promise-like, aka thenable
  
      when.Promise = Promise;              // Promise constructor
      when.defer = defer;                // Create a {promise, resolve, reject} tuple
  
      // Error types
  
      when.TimeoutError = TimeoutError;
  
      /**
       * Get a trusted promise for x, or by transforming x with onFulfilled
       *
       * @param {*} x
       * @param {function?} onFulfilled callback to be called when x is
       *   successfully fulfilled.  If promiseOrValue is an immediate value, callback
       *   will be invoked immediately.
       * @param {function?} onRejected callback to be called when x is
       *   rejected.
       * @param {function?} onProgress callback to be called when progress updates
       *   are issued for x. @deprecated
       * @returns {Promise} a new promise that will fulfill with the return
       *   value of callback or errback or the completion value of promiseOrValue if
       *   callback and/or errback is not supplied.
       */
      function when(x, onFulfilled, onRejected, onProgress) {
        var p = Promise.resolve(x);
        if (arguments.length < 2) {
          return p;
        }
  
        return p.then(onFulfilled, onRejected, onProgress);
      }
  
      /**
       * Creates a new promise whose fate is determined by resolver.
       * @param {function} resolver function(resolve, reject, notify)
       * @returns {Promise} promise whose fate is determine by resolver
       */
      function promise(resolver) {
        return new Promise(resolver);
      }
  
      /**
       * Lift the supplied function, creating a version of f that returns
       * promises, and accepts promises as arguments.
       * @param {function} f
       * @returns {Function} version of f that returns promises
       */
      function lift(f) {
        return function () {
          for (var i = 0, l = arguments.length, a = new Array(l); i < l; ++i) {
            a[i] = arguments[i];
          }
          return apply(f, this, a);
        };
      }
  
      /**
       * Call f in a future turn, with the supplied args, and return a promise
       * for the result.
       * @param {function} f
       * @returns {Promise}
       */
      function attempt(f /*, args... */) {
        /*jshint validthis:true */
        for (var i = 0, l = arguments.length - 1, a = new Array(l); i < l; ++i) {
          a[i] = arguments[i + 1];
        }
        return apply(f, this, a);
      }
  
      /**
       * Creates a {promise, resolver} pair, either or both of which
       * may be given out safely to consumers.
       * @return {{promise: Promise, resolve: function, reject: function, notify: function}}
       */
      function defer() {
        return new Deferred();
      }
  
      function Deferred() {
        var p = Promise._defer();
  
        function resolve(x) {
          p._handler.resolve(x);
        }
  
        function reject(x) {
          p._handler.reject(x);
        }
  
        function notify(x) {
          p._handler.notify(x);
        }
  
        this.promise = p;
        this.resolve = resolve;
        this.reject = reject;
        this.notify = notify;
        this.resolver = {resolve: resolve, reject: reject, notify: notify};
      }
  
      /**
       * Determines if x is promise-like, i.e. a thenable object
       * NOTE: Will return true for *any thenable object*, and isn't truly
       * safe, since it may attempt to access the `then` property of x (i.e.
       *  clever/malicious getters may do weird things)
       * @param {*} x anything
       * @returns {boolean} true if x is promise-like
       */
      function isPromiseLike(x) {
        return x && typeof x.then === 'function';
      }
  
      /**
       * Return a promise that will resolve only once all the supplied arguments
       * have resolved. The resolution value of the returned promise will be an array
       * containing the resolution values of each of the arguments.
       * @param {...*} arguments may be a mix of promises and values
       * @returns {Promise}
       */
      function join(/* ...promises */) {
        return Promise.all(arguments);
      }
  
      /**
       * Return a promise that will fulfill once all input promises have
       * fulfilled, or reject when any one input promise rejects.
       * @param {array|Promise} promises array (or promise for an array) of promises
       * @returns {Promise}
       */
      function all(promises) {
        return when(promises, Promise.all);
      }
  
      /**
       * Return a promise that will always fulfill with an array containing
       * the outcome states of all input promises.  The returned promise
       * will only reject if `promises` itself is a rejected promise.
       * @param {array|Promise} promises array (or promise for an array) of promises
       * @returns {Promise} promise for array of settled state descriptors
       */
      function settle(promises) {
        return when(promises, Promise.settle);
      }
  
      /**
       * Promise-aware array map function, similar to `Array.prototype.map()`,
       * but input array may contain promises or values.
       * @param {Array|Promise} promises array of anything, may contain promises and values
       * @param {function(x:*, index:Number):*} mapFunc map function which may
       *  return a promise or value
       * @returns {Promise} promise that will fulfill with an array of mapped values
       *  or reject if any input promise rejects.
       */
      function map(promises, mapFunc) {
        return when(promises, function (promises) {
          return Promise.map(promises, mapFunc);
        });
      }
  
      /**
       * Filter the provided array of promises using the provided predicate.  Input may
       * contain promises and values
       * @param {Array|Promise} promises array of promises and values
       * @param {function(x:*, index:Number):boolean} predicate filtering predicate.
       *  Must return truthy (or promise for truthy) for items to retain.
       * @returns {Promise} promise that will fulfill with an array containing all items
       *  for which predicate returned truthy.
       */
      function filter(promises, predicate) {
        return when(promises, function (promises) {
          return Promise.filter(promises, predicate);
        });
      }
  
      return when;
    });
  })(typeof define === 'function' && define.amd ? define : function (factory) {
      module.exports = factory(require);
    });
  