diff options
Diffstat (limited to 'common/src/main/webapp/usageguide/appserver/node_modules/mongoose/node_modules/mpromise/lib/promise.js')
-rw-r--r-- | common/src/main/webapp/usageguide/appserver/node_modules/mongoose/node_modules/mpromise/lib/promise.js | 445 |
1 files changed, 445 insertions, 0 deletions
diff --git a/common/src/main/webapp/usageguide/appserver/node_modules/mongoose/node_modules/mpromise/lib/promise.js b/common/src/main/webapp/usageguide/appserver/node_modules/mongoose/node_modules/mpromise/lib/promise.js new file mode 100644 index 00000000..3cb4419b --- /dev/null +++ b/common/src/main/webapp/usageguide/appserver/node_modules/mongoose/node_modules/mpromise/lib/promise.js @@ -0,0 +1,445 @@ +'use strict'; +var util = require('util'); +var EventEmitter = require('events').EventEmitter; +function toArray(arr, start, end) { + return Array.prototype.slice.call(arr, start, end) +} +function strongUnshift(x, arrLike) { + var arr = toArray(arrLike); + arr.unshift(x); + return arr; +} + + +/** + * MPromise constructor. + * + * _NOTE: The success and failure event names can be overridden by setting `Promise.SUCCESS` and `Promise.FAILURE` respectively._ + * + * @param {Function} back a function that accepts `fn(err, ...){}` as signature + * @inherits NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter + * @event `reject`: Emits when the promise is rejected (event name may be overridden) + * @event `fulfill`: Emits when the promise is fulfilled (event name may be overridden) + * @api public + */ +function Promise(back) { + this.emitter = new EventEmitter(); + this.emitted = {}; + this.ended = false; + if ('function' == typeof back) { + this.ended = true; + this.onResolve(back); + } +} + + +/* + * Module exports. + */ +module.exports = Promise; + + +/*! + * event names + */ +Promise.SUCCESS = 'fulfill'; +Promise.FAILURE = 'reject'; + + +/** + * Adds `listener` to the `event`. + * + * If `event` is either the success or failure event and the event has already been emitted, the`listener` is called immediately and passed the results of the original emitted event. + * + * @param {String} event + * @param {Function} callback + * @return {MPromise} this + * @api private + */ +Promise.prototype.on = function (event, callback) { + if (this.emitted[event]) + callback.apply(undefined, this.emitted[event]); + else + this.emitter.on(event, callback); + + return this; +}; + + +/** + * Keeps track of emitted events to run them on `on`. + * + * @api private + */ +Promise.prototype.safeEmit = function (event) { + // ensures a promise can't be fulfill() or reject() more than once + if (event == Promise.SUCCESS || event == Promise.FAILURE) { + if (this.emitted[Promise.SUCCESS] || this.emitted[Promise.FAILURE]) { + return this; + } + this.emitted[event] = toArray(arguments, 1); + } + + this.emitter.emit.apply(this.emitter, arguments); + return this; +}; + + +/** + * @api private + */ +Promise.prototype.hasRejectListeners = function () { + return EventEmitter.listenerCount(this.emitter, Promise.FAILURE) > 0; +}; + + +/** + * Fulfills this promise with passed arguments. + * + * If this promise has already been fulfilled or rejected, no action is taken. + * + * @api public + */ +Promise.prototype.fulfill = function () { + return this.safeEmit.apply(this, strongUnshift(Promise.SUCCESS, arguments)); +}; + + +/** + * Rejects this promise with `reason`. + * + * If this promise has already been fulfilled or rejected, no action is taken. + * + * @api public + * @param {Object|String} reason + * @return {MPromise} this + */ +Promise.prototype.reject = function (reason) { + if (this.ended && !this.hasRejectListeners()) + throw reason; + return this.safeEmit(Promise.FAILURE, reason); +}; + + +/** + * Resolves this promise to a rejected state if `err` is passed or + * fulfilled state if no `err` is passed. + * + * @param {Error} [err] error or null + * @param {Object} [val] value to fulfill the promise with + * @api public + */ +Promise.prototype.resolve = function (err, val) { + if (err) return this.reject(err); + return this.fulfill(val); +}; + + +/** + * Adds a listener to the SUCCESS event. + * + * @return {MPromise} this + * @api public + */ +Promise.prototype.onFulfill = function (fn) { + if (!fn) return this; + if ('function' != typeof fn) throw new TypeError("fn should be a function"); + return this.on(Promise.SUCCESS, fn); +}; + + +/** + * Adds a listener to the FAILURE event. + * + * @return {MPromise} this + * @api public + */ +Promise.prototype.onReject = function (fn) { + if (!fn) return this; + if ('function' != typeof fn) throw new TypeError("fn should be a function"); + return this.on(Promise.FAILURE, fn); +}; + + +/** + * Adds a single function as a listener to both SUCCESS and FAILURE. + * + * It will be executed with traditional node.js argument position: + * function (err, args...) {} + * + * Also marks the promise as `end`ed, since it's the common use-case, and yet has no + * side effects unless `fn` is undefined or null. + * + * @param {Function} fn + * @return {MPromise} this + */ +Promise.prototype.onResolve = function (fn) { + if (!fn) return this; + if ('function' != typeof fn) throw new TypeError("fn should be a function"); + this.on(Promise.FAILURE, function (err) { fn.call(this, err); }); + this.on(Promise.SUCCESS, function () { fn.apply(this, strongUnshift(null, arguments)); }); + return this; +}; + + +/** + * Creates a new promise and returns it. If `onFulfill` or + * `onReject` are passed, they are added as SUCCESS/ERROR callbacks + * to this promise after the next tick. + * + * Conforms to [promises/A+](https://github.com/promises-aplus/promises-spec) specification. Read for more detail how to use this method. + * + * ####Example: + * + * var p = new Promise; + * p.then(function (arg) { + * return arg + 1; + * }).then(function (arg) { + * throw new Error(arg + ' is an error!'); + * }).then(null, function (err) { + * assert.ok(err instanceof Error); + * assert.equal('2 is an error', err.message); + * }); + * p.complete(1); + * + * @see promises-A+ https://github.com/promises-aplus/promises-spec + * @param {Function} onFulfill + * @param {Function} [onReject] + * @return {MPromise} newPromise + */ +Promise.prototype.then = function (onFulfill, onReject) { + var newPromise = new Promise; + + if ('function' == typeof onFulfill) { + this.onFulfill(handler(newPromise, onFulfill)); + } else { + this.onFulfill(newPromise.fulfill.bind(newPromise)); + } + + if ('function' == typeof onReject) { + this.onReject(handler(newPromise, onReject)); + } else { + this.onReject(newPromise.reject.bind(newPromise)); + } + + return newPromise; +}; + + +function handler(promise, fn) { + function newTickHandler() { + var pDomain = promise.emitter.domain; + if (pDomain && pDomain !== process.domain) pDomain.enter(); + try { + var x = fn.apply(undefined, boundHandler.args); + } catch (err) { + promise.reject(err); + return; + } + resolve(promise, x); + } + function boundHandler() { + boundHandler.args = arguments; + process.nextTick(newTickHandler); + } + return boundHandler; +} + + +function resolve(promise, x) { + function fulfillOnce() { + if (done++) return; + resolve.apply(undefined, strongUnshift(promise, arguments)); + } + function rejectOnce(reason) { + if (done++) return; + promise.reject(reason); + } + + if (promise === x) { + promise.reject(new TypeError("promise and x are the same")); + return; + } + var rest = toArray(arguments, 1); + var type = typeof x; + if ('undefined' == type || null == x || !('object' == type || 'function' == type)) { + promise.fulfill.apply(promise, rest); + return; + } + + try { + var theThen = x.then; + } catch (err) { + promise.reject(err); + return; + } + + if ('function' != typeof theThen) { + promise.fulfill.apply(promise, rest); + return; + } + + var done = 0; + try { + var ret = theThen.call(x, fulfillOnce, rejectOnce); + return ret; + } catch (err) { + if (done++) return; + promise.reject(err); + } +} + + +/** + * Signifies that this promise was the last in a chain of `then()s`: if a handler passed to the call to `then` which produced this promise throws, the exception will go uncaught. + * + * ####Example: + * + * var p = new Promise; + * p.then(function(){ throw new Error('shucks') }); + * setTimeout(function () { + * p.fulfill(); + * // error was caught and swallowed by the promise returned from + * // p.then(). we either have to always register handlers on + * // the returned promises or we can do the following... + * }, 10); + * + * // this time we use .end() which prevents catching thrown errors + * var p = new Promise; + * var p2 = p.then(function(){ throw new Error('shucks') }).end(); // <-- + * setTimeout(function () { + * p.fulfill(); // throws "shucks" + * }, 10); + * + * @api public + * @param {Function} [onReject] + * @return {MPromise} this + */ +Promise.prototype.end = Promise.prototype['catch'] = function (onReject) { + if (!onReject && !this.hasRejectListeners()) + onReject = function idRejector(e) { throw e; }; + this.onReject(onReject); + this.ended = true; + return this; +}; + + +/** + * A debug utility function that adds handlers to a promise that will log some output to the `console` + * + * ####Example: + * + * var p = new Promise; + * p.then(function(){ throw new Error('shucks') }); + * setTimeout(function () { + * p.fulfill(); + * // error was caught and swallowed by the promise returned from + * // p.then(). we either have to always register handlers on + * // the returned promises or we can do the following... + * }, 10); + * + * // this time we use .end() which prevents catching thrown errors + * var p = new Promise; + * var p2 = p.then(function(){ throw new Error('shucks') }).end(); // <-- + * setTimeout(function () { + * p.fulfill(); // throws "shucks" + * }, 10); + * + * @api public + * @param {MPromise} p + * @param {String} name + * @return {MPromise} this + */ +Promise.trace = function (p, name) { + p.then( + function () { + console.log("%s fulfill %j", name, toArray(arguments)); + }, + function () { + console.log("%s reject %j", name, toArray(arguments)); + } + ) +}; + + +Promise.prototype.chain = function (p2) { + var p1 = this; + p1.onFulfill(p2.fulfill.bind(p2)); + p1.onReject(p2.reject.bind(p2)); + return p2; +}; + + +Promise.prototype.all = function (promiseOfArr) { + var pRet = new Promise; + this.then(promiseOfArr).then( + function (promiseArr) { + var count = 0; + var ret = []; + var errSentinel; + if (!promiseArr.length) pRet.resolve(); + promiseArr.forEach(function (promise, index) { + if (errSentinel) return; + count++; + promise.then( + function (val) { + if (errSentinel) return; + ret[index] = val; + --count; + if (count == 0) pRet.fulfill(ret); + }, + function (err) { + if (errSentinel) return; + errSentinel = err; + pRet.reject(err); + } + ); + }); + return pRet; + } + , pRet.reject.bind(pRet) + ); + return pRet; +}; + + +Promise.hook = function (arr) { + var p1 = new Promise; + var pFinal = new Promise; + var signalP = function () { + --count; + if (count == 0) + pFinal.fulfill(); + return pFinal; + }; + var count = 1; + var ps = p1; + arr.forEach(function (hook) { + ps = ps.then( + function () { + var p = new Promise; + count++; + hook(p.resolve.bind(p), signalP); + return p; + } + ) + }); + ps = ps.then(signalP); + p1.resolve(); + return ps; +}; + + +/* This is for the A+ tests, but it's very useful as well */ +Promise.fulfilled = function fulfilled() { var p = new Promise; p.fulfill.apply(p, arguments); return p; }; +Promise.rejected = function rejected(reason) { return new Promise().reject(reason); }; +Promise.deferred = function deferred() { + var p = new Promise; + return { + promise: p, + reject: p.reject.bind(p), + resolve: p.fulfill.bind(p), + callback: p.resolve.bind(p) + } +}; +/* End A+ tests adapter bit */ |