/* */ 
(function(process) {
  "use strict";
  module.exports = function() {
    var makeSelfResolutionError = function() {
      return new TypeError("circular promise resolution chain\u000a\u000a    See http://goo.gl/MqrFmX\u000a");
    };
    var reflectHandler = function() {
      return new Promise.PromiseInspection(this._target());
    };
    var apiRejection = function(msg) {
      return Promise.reject(new TypeError(msg));
    };
    function Proxyable() {}
    var UNDEFINED_BINDING = {};
    var util = require('./util');
    var getDomain;
    if (util.isNode) {
      getDomain = function() {
        var ret = process.domain;
        if (ret === undefined)
          ret = null;
        return ret;
      };
    } else {
      getDomain = function() {
        return null;
      };
    }
    util.notEnumerableProp(Promise, "_getDomain", getDomain);
    var es5 = require('./es5');
    var Async = require('./async');
    var async = new Async();
    es5.defineProperty(Promise, "_async", {value: async});
    var errors = require('./errors');
    var TypeError = Promise.TypeError = errors.TypeError;
    Promise.RangeError = errors.RangeError;
    var CancellationError = Promise.CancellationError = errors.CancellationError;
    Promise.TimeoutError = errors.TimeoutError;
    Promise.OperationalError = errors.OperationalError;
    Promise.RejectionError = errors.OperationalError;
    Promise.AggregateError = errors.AggregateError;
    var INTERNAL = function() {};
    var APPLY = {};
    var NEXT_FILTER = {};
    var tryConvertToPromise = require('./thenables')(Promise, INTERNAL);
    var PromiseArray = require('./promise_array')(Promise, INTERNAL, tryConvertToPromise, apiRejection, Proxyable);
    var Context = require('./context')(Promise);
    var createContext = Context.create;
    var debug = require('./debuggability')(Promise, Context);
    var CapturedTrace = debug.CapturedTrace;
    var finallyHandler = require('./finally')(Promise, tryConvertToPromise);
    var catchFilter = require('./catch_filter')(NEXT_FILTER);
    var nodebackForPromise = require('./nodeback');
    var errorObj = util.errorObj;
    var tryCatch = util.tryCatch;
    function check(self, executor) {
      if (typeof executor !== "function") {
        throw new TypeError("expecting a function but got " + util.classString(executor));
      }
      if (self.constructor !== Promise) {
        throw new TypeError("the promise constructor cannot be invoked directly\u000a\u000a    See http://goo.gl/MqrFmX\u000a");
      }
    }
    function Promise(executor) {
      this._bitField = 0;
      this._fulfillmentHandler0 = undefined;
      this._rejectionHandler0 = undefined;
      this._promise0 = undefined;
      this._receiver0 = undefined;
      if (executor !== INTERNAL) {
        check(this, executor);
        this._resolveFromExecutor(executor);
      }
      this._promiseCreated();
    }
    Promise.prototype.toString = function() {
      return "[object Promise]";
    };
    Promise.prototype.caught = Promise.prototype["catch"] = function(fn) {
      var len = arguments.length;
      if (len > 1) {
        var catchInstances = new Array(len - 1),
            j = 0,
            i;
        for (i = 0; i < len - 1; ++i) {
          var item = arguments[i];
          if (util.isObject(item)) {
            catchInstances[j++] = item;
          } else {
            return apiRejection("expecting an object but got " + util.classString(item));
          }
        }
        catchInstances.length = j;
        fn = arguments[i];
        return this.then(undefined, catchFilter(catchInstances, fn, this));
      }
      return this.then(undefined, fn);
    };
    Promise.prototype.reflect = function() {
      return this._then(reflectHandler, reflectHandler, undefined, this, undefined);
    };
    Promise.prototype.then = function(didFulfill, didReject) {
      if (debug.warnings() && arguments.length > 0 && typeof didFulfill !== "function" && typeof didReject !== "function") {
        var msg = ".then() only accepts functions but was passed: " + util.classString(didFulfill);
        if (arguments.length > 1) {
          msg += ", " + util.classString(didReject);
        }
        this._warn(msg);
      }
      return this._then(didFulfill, didReject, undefined, undefined, undefined);
    };
    Promise.prototype.done = function(didFulfill, didReject) {
      var promise = this._then(didFulfill, didReject, undefined, undefined, undefined);
      promise._setIsFinal();
    };
    Promise.prototype.spread = function(fn) {
      if (typeof fn !== "function") {
        return apiRejection("expecting a function but got " + util.classString(fn));
      }
      return this.all()._then(fn, undefined, undefined, APPLY, undefined);
    };
    Promise.prototype.toJSON = function() {
      var ret = {
        isFulfilled: false,
        isRejected: false,
        fulfillmentValue: undefined,
        rejectionReason: undefined
      };
      if (this.isFulfilled()) {
        ret.fulfillmentValue = this.value();
        ret.isFulfilled = true;
      } else if (this.isRejected()) {
        ret.rejectionReason = this.reason();
        ret.isRejected = true;
      }
      return ret;
    };
    Promise.prototype.all = function() {
      if (arguments.length > 0) {
        this._warn(".all() was passed arguments but it does not take any");
      }
      return new PromiseArray(this).promise();
    };
    Promise.prototype.error = function(fn) {
      return this.caught(util.originatesFromRejection, fn);
    };
    Promise.is = function(val) {
      return val instanceof Promise;
    };
    Promise.fromNode = Promise.fromCallback = function(fn) {
      var ret = new Promise(INTERNAL);
      var multiArgs = arguments.length > 1 ? !!Object(arguments[1]).multiArgs : false;
      var result = tryCatch(fn)(nodebackForPromise(ret, multiArgs));
      if (result === errorObj) {
        ret._rejectCallback(result.e, true);
      }
      if (!ret._isFateSealed())
        ret._setAsyncGuaranteed();
      return ret;
    };
    Promise.all = function(promises) {
      return new PromiseArray(promises).promise();
    };
    Promise.cast = function(obj) {
      var ret = tryConvertToPromise(obj);
      if (!(ret instanceof Promise)) {
        ret = new Promise(INTERNAL);
        ret._captureStackTrace();
        ret._setFulfilled();
        ret._rejectionHandler0 = obj;
      }
      return ret;
    };
    Promise.resolve = Promise.fulfilled = Promise.cast;
    Promise.reject = Promise.rejected = function(reason) {
      var ret = new Promise(INTERNAL);
      ret._captureStackTrace();
      ret._rejectCallback(reason, true);
      return ret;
    };
    Promise.setScheduler = function(fn) {
      if (typeof fn !== "function") {
        throw new TypeError("expecting a function but got " + util.classString(fn));
      }
      var prev = async._schedule;
      async._schedule = fn;
      return prev;
    };
    Promise.prototype._then = function(didFulfill, didReject, _, receiver, internalData) {
      var haveInternalData = internalData !== undefined;
      var promise = haveInternalData ? internalData : new Promise(INTERNAL);
      var target = this._target();
      var bitField = target._bitField;
      if (!haveInternalData) {
        promise._propagateFrom(this, 3);
        promise._captureStackTrace();
        if (receiver === undefined && ((this._bitField & 2097152) !== 0)) {
          if (!((bitField & 50397184) === 0)) {
            receiver = this._boundValue();
          } else {
            receiver = target === this ? undefined : this._boundTo;
          }
        }
      }
      var domain = getDomain();
      if (!((bitField & 50397184) === 0)) {
        var handler,
            value,
            settler = target._settlePromiseCtx;
        if (((bitField & 33554432) !== 0)) {
          value = target._rejectionHandler0;
          handler = didFulfill;
        } else if (((bitField & 16777216) !== 0)) {
          value = target._fulfillmentHandler0;
          handler = didReject;
          target._unsetRejectionIsUnhandled();
        } else {
          settler = target._settlePromiseLateCancellationObserver;
          value = new CancellationError("late cancellation observer");
          target._attachExtraTrace(value);
          handler = didReject;
        }
        async.invoke(settler, target, {
          handler: domain === null ? handler : (typeof handler === "function" && domain.bind(handler)),
          promise: promise,
          receiver: receiver,
          value: value
        });
      } else {
        target._addCallbacks(didFulfill, didReject, promise, receiver, domain);
      }
      return promise;
    };
    Promise.prototype._length = function() {
      return this._bitField & 65535;
    };
    Promise.prototype._isFateSealed = function() {
      return (this._bitField & 117506048) !== 0;
    };
    Promise.prototype._isFollowing = function() {
      return (this._bitField & 67108864) === 67108864;
    };
    Promise.prototype._setLength = function(len) {
      this._bitField = (this._bitField & -65536) | (len & 65535);
    };
    Promise.prototype._setFulfilled = function() {
      this._bitField = this._bitField | 33554432;
    };
    Promise.prototype._setRejected = function() {
      this._bitField = this._bitField | 16777216;
    };
    Promise.prototype._setFollowing = function() {
      this._bitField = this._bitField | 67108864;
    };
    Promise.prototype._setIsFinal = function() {
      this._bitField = this._bitField | 4194304;
    };
    Promise.prototype._isFinal = function() {
      return (this._bitField & 4194304) > 0;
    };
    Promise.prototype._unsetCancelled = function() {
      this._bitField = this._bitField & (~65536);
    };
    Promise.prototype._setCancelled = function() {
      this._bitField = this._bitField | 65536;
    };
    Promise.prototype._setAsyncGuaranteed = function() {
      this._bitField = this._bitField | 134217728;
    };
    Promise.prototype._receiverAt = function(index) {
      var ret = index === 0 ? this._receiver0 : this[index * 4 - 4 + 3];
      if (ret === UNDEFINED_BINDING) {
        return undefined;
      } else if (ret === undefined && this._isBound()) {
        return this._boundValue();
      }
      return ret;
    };
    Promise.prototype._promiseAt = function(index) {
      return this[index * 4 - 4 + 2];
    };
    Promise.prototype._fulfillmentHandlerAt = function(index) {
      return this[index * 4 - 4 + 0];
    };
    Promise.prototype._rejectionHandlerAt = function(index) {
      return this[index * 4 - 4 + 1];
    };
    Promise.prototype._boundValue = function() {};
    Promise.prototype._migrateCallback0 = function(follower) {
      var bitField = follower._bitField;
      var fulfill = follower._fulfillmentHandler0;
      var reject = follower._rejectionHandler0;
      var promise = follower._promise0;
      var receiver = follower._receiverAt(0);
      if (receiver === undefined)
        receiver = UNDEFINED_BINDING;
      this._addCallbacks(fulfill, reject, promise, receiver, null);
    };
    Promise.prototype._migrateCallbackAt = function(follower, index) {
      var fulfill = follower._fulfillmentHandlerAt(index);
      var reject = follower._rejectionHandlerAt(index);
      var promise = follower._promiseAt(index);
      var receiver = follower._receiverAt(index);
      if (receiver === undefined)
        receiver = UNDEFINED_BINDING;
      this._addCallbacks(fulfill, reject, promise, receiver, null);
    };
    Promise.prototype._addCallbacks = function(fulfill, reject, promise, receiver, domain) {
      var index = this._length();
      if (index >= 65535 - 4) {
        index = 0;
        this._setLength(0);
      }
      if (index === 0) {
        this._promise0 = promise;
        this._receiver0 = receiver;
        if (typeof fulfill === "function") {
          this._fulfillmentHandler0 = domain === null ? fulfill : domain.bind(fulfill);
        }
        if (typeof reject === "function") {
          this._rejectionHandler0 = domain === null ? reject : domain.bind(reject);
        }
      } else {
        var base = index * 4 - 4;
        this[base + 2] = promise;
        this[base + 3] = receiver;
        if (typeof fulfill === "function") {
          this[base + 0] = domain === null ? fulfill : domain.bind(fulfill);
        }
        if (typeof reject === "function") {
          this[base + 1] = domain === null ? reject : domain.bind(reject);
        }
      }
      this._setLength(index + 1);
      return index;
    };
    Promise.prototype._proxy = function(proxyable, arg) {
      this._addCallbacks(undefined, undefined, arg, proxyable, null);
    };
    Promise.prototype._resolveCallback = function(value, shouldBind) {
      if (((this._bitField & 117506048) !== 0))
        return;
      if (value === this)
        return this._rejectCallback(makeSelfResolutionError(), false);
      var maybePromise = tryConvertToPromise(value, this);
      if (!(maybePromise instanceof Promise))
        return this._fulfill(value);
      if (shouldBind)
        this._propagateFrom(maybePromise, 2);
      var promise = maybePromise._target();
      var bitField = promise._bitField;
      if (((bitField & 50397184) === 0)) {
        var len = this._length();
        if (len > 0)
          promise._migrateCallback0(this);
        for (var i = 1; i < len; ++i) {
          promise._migrateCallbackAt(this, i);
        }
        this._setFollowing();
        this._setLength(0);
        this._setFollowee(promise);
      } else if (((bitField & 33554432) !== 0)) {
        this._fulfill(promise._value());
      } else if (((bitField & 16777216) !== 0)) {
        this._reject(promise._reason());
      } else {
        var reason = new CancellationError("late cancellation observer");
        promise._attachExtraTrace(reason);
        this._reject(reason);
      }
    };
    Promise.prototype._rejectCallback = function(reason, synchronous, ignoreNonErrorWarnings) {
      var trace = util.ensureErrorObject(reason);
      var hasStack = trace === reason;
      if (!hasStack && !ignoreNonErrorWarnings && debug.warnings()) {
        var message = "a promise was rejected with a non-error: " + util.classString(reason);
        this._warn(message, true);
      }
      this._attachExtraTrace(trace, synchronous ? hasStack : false);
      this._reject(reason);
    };
    Promise.prototype._resolveFromExecutor = function(executor) {
      var promise = this;
      this._captureStackTrace();
      this._pushContext();
      var synchronous = true;
      var r = this._execute(executor, function(value) {
        promise._resolveCallback(value);
      }, function(reason) {
        promise._rejectCallback(reason, synchronous);
      });
      synchronous = false;
      this._popContext();
      if (r !== undefined) {
        promise._rejectCallback(r, true);
      }
    };
    Promise.prototype._settlePromiseFromHandler = function(handler, receiver, value, promise) {
      var bitField = promise._bitField;
      if (((bitField & 65536) !== 0))
        return;
      promise._pushContext();
      var x;
      if (receiver === APPLY) {
        if (!value || typeof value.length !== "number") {
          x = errorObj;
          x.e = new TypeError("cannot .spread() a non-array: " + util.classString(value));
        } else {
          x = tryCatch(handler).apply(this._boundValue(), value);
        }
      } else {
        x = tryCatch(handler).call(receiver, value);
      }
      var promiseCreated = promise._popContext();
      bitField = promise._bitField;
      if (((bitField & 65536) !== 0))
        return;
      if (x === NEXT_FILTER) {
        promise._reject(value);
      } else if (x === errorObj || x === promise) {
        var err = x === promise ? makeSelfResolutionError() : x.e;
        promise._rejectCallback(err, false);
      } else {
        debug.checkForgottenReturns(x, promiseCreated, "", promise, this);
        promise._resolveCallback(x);
      }
    };
    Promise.prototype._target = function() {
      var ret = this;
      while (ret._isFollowing())
        ret = ret._followee();
      return ret;
    };
    Promise.prototype._followee = function() {
      return this._rejectionHandler0;
    };
    Promise.prototype._setFollowee = function(promise) {
      this._rejectionHandler0 = promise;
    };
    Promise.prototype._settlePromise = function(promise, handler, receiver, value) {
      var isPromise = promise instanceof Promise;
      var bitField = this._bitField;
      var asyncGuaranteed = ((bitField & 134217728) !== 0);
      if (((bitField & 65536) !== 0)) {
        if (isPromise)
          promise._invokeInternalOnCancel();
        if (handler === finallyHandler) {
          receiver.cancelPromise = promise;
          if (tryCatch(handler).call(receiver, value) === errorObj) {
            promise._reject(errorObj.e);
          }
        } else if (handler === reflectHandler) {
          promise._fulfill(reflectHandler.call(receiver));
        } else if (receiver instanceof Proxyable) {
          receiver._promiseCancelled(promise);
        } else if (isPromise || promise instanceof PromiseArray) {
          promise._cancel();
        } else {
          receiver.cancel();
        }
      } else if (typeof handler === "function") {
        if (!isPromise) {
          handler.call(receiver, value, promise);
        } else {
          if (asyncGuaranteed)
            promise._setAsyncGuaranteed();
          this._settlePromiseFromHandler(handler, receiver, value, promise);
        }
      } else if (receiver instanceof Proxyable) {
        if (!receiver._isResolved()) {
          if (((bitField & 33554432) !== 0)) {
            receiver._promiseFulfilled(value, promise);
          } else {
            receiver._promiseRejected(value, promise);
          }
        }
      } else if (isPromise) {
        if (asyncGuaranteed)
          promise._setAsyncGuaranteed();
        if (((bitField & 33554432) !== 0)) {
          promise._fulfill(value);
        } else {
          promise._reject(value);
        }
      }
    };
    Promise.prototype._settlePromiseLateCancellationObserver = function(ctx) {
      var handler = ctx.handler;
      var promise = ctx.promise;
      var receiver = ctx.receiver;
      var value = ctx.value;
      if (typeof handler === "function") {
        if (!(promise instanceof Promise)) {
          handler.call(receiver, value, promise);
        } else {
          this._settlePromiseFromHandler(handler, receiver, value, promise);
        }
      } else if (promise instanceof Promise) {
        promise._reject(value);
      }
    };
    Promise.prototype._settlePromiseCtx = function(ctx) {
      this._settlePromise(ctx.promise, ctx.handler, ctx.receiver, ctx.value);
    };
    Promise.prototype._settlePromise0 = function(handler, value, bitField) {
      var promise = this._promise0;
      var receiver = this._receiverAt(0);
      this._promise0 = undefined;
      this._receiver0 = undefined;
      this._settlePromise(promise, handler, receiver, value);
    };
    Promise.prototype._clearCallbackDataAtIndex = function(index) {
      var base = index * 4 - 4;
      this[base + 2] = this[base + 3] = this[base + 0] = this[base + 1] = undefined;
    };
    Promise.prototype._fulfill = function(value) {
      var bitField = this._bitField;
      if (((bitField & 117506048) >>> 16))
        return;
      if (value === this) {
        var err = makeSelfResolutionError();
        this._attachExtraTrace(err);
        return this._reject(err);
      }
      this._setFulfilled();
      this._rejectionHandler0 = value;
      if ((bitField & 65535) > 0) {
        if (((bitField & 134217728) !== 0)) {
          this._settlePromises();
        } else {
          async.settlePromises(this);
        }
      }
    };
    Promise.prototype._reject = function(reason) {
      var bitField = this._bitField;
      if (((bitField & 117506048) >>> 16))
        return;
      this._setRejected();
      this._fulfillmentHandler0 = reason;
      if (this._isFinal()) {
        return async.fatalError(reason, util.isNode);
      }
      if ((bitField & 65535) > 0) {
        if (((bitField & 134217728) !== 0)) {
          this._settlePromises();
        } else {
          async.settlePromises(this);
        }
      } else {
        this._ensurePossibleRejectionHandled();
      }
    };
    Promise.prototype._fulfillPromises = function(len, value) {
      for (var i = 1; i < len; i++) {
        var handler = this._fulfillmentHandlerAt(i);
        var promise = this._promiseAt(i);
        var receiver = this._receiverAt(i);
        this._clearCallbackDataAtIndex(i);
        this._settlePromise(promise, handler, receiver, value);
      }
    };
    Promise.prototype._rejectPromises = function(len, reason) {
      for (var i = 1; i < len; i++) {
        var handler = this._rejectionHandlerAt(i);
        var promise = this._promiseAt(i);
        var receiver = this._receiverAt(i);
        this._clearCallbackDataAtIndex(i);
        this._settlePromise(promise, handler, receiver, reason);
      }
    };
    Promise.prototype._settlePromises = function() {
      var bitField = this._bitField;
      var len = (bitField & 65535);
      if (len > 0) {
        if (((bitField & 16842752) !== 0)) {
          var reason = this._fulfillmentHandler0;
          this._settlePromise0(this._rejectionHandler0, reason, bitField);
          this._rejectPromises(len, reason);
        } else {
          var value = this._rejectionHandler0;
          this._settlePromise0(this._fulfillmentHandler0, value, bitField);
          this._fulfillPromises(len, value);
        }
        this._setLength(0);
      }
      this._clearCancellationData();
    };
    Promise.prototype._settledValue = function() {
      var bitField = this._bitField;
      if (((bitField & 33554432) !== 0)) {
        return this._rejectionHandler0;
      } else if (((bitField & 16777216) !== 0)) {
        return this._fulfillmentHandler0;
      }
    };
    function deferResolve(v) {
      this.promise._resolveCallback(v);
    }
    function deferReject(v) {
      this.promise._rejectCallback(v, false);
    }
    Promise.defer = Promise.pending = function() {
      debug.deprecated("Promise.defer", "new Promise");
      var promise = new Promise(INTERNAL);
      return {
        promise: promise,
        resolve: deferResolve,
        reject: deferReject
      };
    };
    util.notEnumerableProp(Promise, "_makeSelfResolutionError", makeSelfResolutionError);
    require('./method')(Promise, INTERNAL, tryConvertToPromise, apiRejection, debug);
    require('./bind')(Promise, INTERNAL, tryConvertToPromise, debug);
    require('./cancel')(Promise, PromiseArray, apiRejection, debug);
    require('./direct_resolve')(Promise);
    require('./synchronous_inspection')(Promise);
    require('./join')(Promise, PromiseArray, tryConvertToPromise, INTERNAL, debug);
    Promise.Promise = Promise;
    require('./map')(Promise, PromiseArray, apiRejection, tryConvertToPromise, INTERNAL, debug);
    require('./using')(Promise, apiRejection, tryConvertToPromise, createContext, INTERNAL, debug);
    require('./timers')(Promise, INTERNAL);
    require('./generators')(Promise, apiRejection, INTERNAL, tryConvertToPromise, Proxyable, debug);
    require('./nodeify')(Promise);
    require('./call_get')(Promise);
    require('./props')(Promise, PromiseArray, tryConvertToPromise, apiRejection);
    require('./race')(Promise, INTERNAL, tryConvertToPromise, apiRejection);
    require('./reduce')(Promise, PromiseArray, apiRejection, tryConvertToPromise, INTERNAL, debug);
    require('./settle')(Promise, PromiseArray, debug);
    require('./some')(Promise, PromiseArray, apiRejection);
    require('./promisify')(Promise, INTERNAL);
    require('./any')(Promise);
    require('./each')(Promise, INTERNAL);
    require('./filter')(Promise, INTERNAL);
    util.toFastProperties(Promise);
    util.toFastProperties(Promise.prototype);
    function fillTypes(value) {
      var p = new Promise(INTERNAL);
      p._fulfillmentHandler0 = value;
      p._rejectionHandler0 = value;
      p._promise0 = value;
      p._receiver0 = value;
    }
    fillTypes({a: 1});
    fillTypes({b: 2});
    fillTypes({c: 3});
    fillTypes(1);
    fillTypes(function() {});
    fillTypes(undefined);
    fillTypes(false);
    fillTypes(new Promise(INTERNAL));
    debug.setBounds(Async.firstLineError, util.lastLineError);
    return Promise;
  };
})(require('process'));
