/*!
* @overview RSVP - a tiny implementation of Promises/A+. * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors * @license Licensed under MIT license * See https://raw.githubusercontent.com/tildeio/rsvp.js/master/LICENSE * @version 3.0.14 */
(function() {
"use strict"; function $$rsvp$events$$indexOf(callbacks, callback) { for (var i=0, l=callbacks.length; i<l; i++) { if (callbacks[i] === callback) { return i; } } return -1; } function $$rsvp$events$$callbacksFor(object) { var callbacks = object._promiseCallbacks; if (!callbacks) { callbacks = object._promiseCallbacks = {}; } return callbacks; } var $$rsvp$events$$default = { /** `RSVP.EventTarget.mixin` extends an object with EventTarget methods. For Example: ```javascript var object = {}; RSVP.EventTarget.mixin(object); object.on('finished', function(event) { // handle event }); object.trigger('finished', { detail: value }); ``` `EventTarget.mixin` also works with prototypes: ```javascript var Person = function() {}; RSVP.EventTarget.mixin(Person.prototype); var yehuda = new Person(); var tom = new Person(); yehuda.on('poke', function(event) { console.log('Yehuda says OW'); }); tom.on('poke', function(event) { console.log('Tom says OW'); }); yehuda.trigger('poke'); tom.trigger('poke'); ``` @method mixin @for RSVP.EventTarget @private @param {Object} object object to extend with EventTarget methods */ mixin: function(object) { object.on = this.on; object.off = this.off; object.trigger = this.trigger; object._promiseCallbacks = undefined; return object; }, /** Registers a callback to be executed when `eventName` is triggered ```javascript object.on('event', function(eventInfo){ // handle the event }); object.trigger('event'); ``` @method on @for RSVP.EventTarget @private @param {String} eventName name of the event to listen for @param {Function} callback function to be called when the event is triggered. */ on: function(eventName, callback) { var allCallbacks = $$rsvp$events$$callbacksFor(this), callbacks; callbacks = allCallbacks[eventName]; if (!callbacks) { callbacks = allCallbacks[eventName] = []; } if ($$rsvp$events$$indexOf(callbacks, callback) === -1) { callbacks.push(callback); } }, /** You can use `off` to stop firing a particular callback for an event: ```javascript function doStuff() { // do stuff! } object.on('stuff', doStuff); object.trigger('stuff'); // doStuff will be called // Unregister ONLY the doStuff callback object.off('stuff', doStuff); object.trigger('stuff'); // doStuff will NOT be called ``` If you don't pass a `callback` argument to `off`, ALL callbacks for the event will not be executed when the event fires. For example: ```javascript var callback1 = function(){}; var callback2 = function(){}; object.on('stuff', callback1); object.on('stuff', callback2); object.trigger('stuff'); // callback1 and callback2 will be executed. object.off('stuff'); object.trigger('stuff'); // callback1 and callback2 will not be executed! ``` @method off @for RSVP.EventTarget @private @param {String} eventName event to stop listening to @param {Function} callback optional argument. If given, only the function given will be removed from the event's callback queue. If no `callback` argument is given, all callbacks will be removed from the event's callback queue. */ off: function(eventName, callback) { var allCallbacks = $$rsvp$events$$callbacksFor(this), callbacks, index; if (!callback) { allCallbacks[eventName] = []; return; } callbacks = allCallbacks[eventName]; index = $$rsvp$events$$indexOf(callbacks, callback); if (index !== -1) { callbacks.splice(index, 1); } }, /** Use `trigger` to fire custom events. For example: ```javascript object.on('foo', function(){ console.log('foo event happened!'); }); object.trigger('foo'); // 'foo event happened!' logged to the console ``` You can also pass a value as a second argument to `trigger` that will be passed as an argument to all event listeners for the event: ```javascript object.on('foo', function(value){ console.log(value.name); }); object.trigger('foo', { name: 'bar' }); // 'bar' logged to the console ``` @method trigger @for RSVP.EventTarget @private @param {String} eventName name of the event to be triggered @param {Any} options optional value to be passed to any event handlers for the given `eventName` */ trigger: function(eventName, options) { var allCallbacks = $$rsvp$events$$callbacksFor(this), callbacks, callback; if (callbacks = allCallbacks[eventName]) { // Don't cache the callbacks.length since it may grow for (var i=0; i<callbacks.length; i++) { callback = callbacks[i]; callback(options); } } } }; var $$rsvp$config$$config = { instrument: false }; $$rsvp$events$$default.mixin($$rsvp$config$$config); function $$rsvp$config$$configure(name, value) { if (name === 'onerror') { // handle for legacy users that expect the actual // error to be passed to their function added via // `RSVP.configure('onerror', someFunctionHere);` $$rsvp$config$$config.on('error', value); return; } if (arguments.length === 2) { $$rsvp$config$$config[name] = value; } else { return $$rsvp$config$$config[name]; } } function $$utils$$objectOrFunction(x) { return typeof x === 'function' || (typeof x === 'object' && x !== null); } function $$utils$$isFunction(x) { return typeof x === 'function'; } function $$utils$$isMaybeThenable(x) { return typeof x === 'object' && x !== null; } var $$utils$$_isArray; if (!Array.isArray) { $$utils$$_isArray = function (x) { return Object.prototype.toString.call(x) === '[object Array]'; }; } else { $$utils$$_isArray = Array.isArray; } var $$utils$$isArray = $$utils$$_isArray; var $$utils$$now = Date.now || function() { return new Date().getTime(); }; function $$utils$$F() { } var $$utils$$o_create = (Object.create || function (o) { if (arguments.length > 1) { throw new Error('Second argument not supported'); } if (typeof o !== 'object') { throw new TypeError('Argument must be an object'); } $$utils$$F.prototype = o; return new $$utils$$F(); }); var $$instrument$$queue = []; var $$instrument$$default = function instrument(eventName, promise, child) { if (1 === $$instrument$$queue.push({ name: eventName, payload: { guid: promise._guidKey + promise._id, eventName: eventName, detail: promise._result, childGuid: child && promise._guidKey + child._id, label: promise._label, timeStamp: $$utils$$now(), stack: new Error(promise._label).stack }})) { setTimeout(function() { var entry; for (var i = 0; i < $$instrument$$queue.length; i++) { entry = $$instrument$$queue[i]; $$rsvp$config$$config.trigger(entry.name, entry.payload); } $$instrument$$queue.length = 0; }, 50); } }; function $$$internal$$noop() {} var $$$internal$$PENDING = void 0; var $$$internal$$FULFILLED = 1; var $$$internal$$REJECTED = 2; var $$$internal$$GET_THEN_ERROR = new $$$internal$$ErrorObject(); function $$$internal$$getThen(promise) { try { return promise.then; } catch(error) { $$$internal$$GET_THEN_ERROR.error = error; return $$$internal$$GET_THEN_ERROR; } } function $$$internal$$tryThen(then, value, fulfillmentHandler, rejectionHandler) { try { then.call(value, fulfillmentHandler, rejectionHandler); } catch(e) { return e; } } function $$$internal$$handleForeignThenable(promise, thenable, then) { $$rsvp$config$$config.async(function(promise) { var sealed = false; var error = $$$internal$$tryThen(then, thenable, function(value) { if (sealed) { return; } sealed = true; if (thenable !== value) { $$$internal$$resolve(promise, value); } else { $$$internal$$fulfill(promise, value); } }, function(reason) { if (sealed) { return; } sealed = true; $$$internal$$reject(promise, reason); }, 'Settle: ' + (promise._label || ' unknown promise')); if (!sealed && error) { sealed = true; $$$internal$$reject(promise, error); } }, promise); } function $$$internal$$handleOwnThenable(promise, thenable) { if (thenable._state === $$$internal$$FULFILLED) { $$$internal$$fulfill(promise, thenable._result); } else if (promise._state === $$$internal$$REJECTED) { $$$internal$$reject(promise, thenable._result); } else { $$$internal$$subscribe(thenable, undefined, function(value) { if (thenable !== value) { $$$internal$$resolve(promise, value); } else { $$$internal$$fulfill(promise, value); } }, function(reason) { $$$internal$$reject(promise, reason); }); } } function $$$internal$$handleMaybeThenable(promise, maybeThenable) { if (maybeThenable.constructor === promise.constructor) { $$$internal$$handleOwnThenable(promise, maybeThenable); } else { var then = $$$internal$$getThen(maybeThenable); if (then === $$$internal$$GET_THEN_ERROR) { $$$internal$$reject(promise, $$$internal$$GET_THEN_ERROR.error); } else if (then === undefined) { $$$internal$$fulfill(promise, maybeThenable); } else if ($$utils$$isFunction(then)) { $$$internal$$handleForeignThenable(promise, maybeThenable, then); } else { $$$internal$$fulfill(promise, maybeThenable); } } } function $$$internal$$resolve(promise, value) { if (promise === value) { $$$internal$$fulfill(promise, value); } else if ($$utils$$objectOrFunction(value)) { $$$internal$$handleMaybeThenable(promise, value); } else { $$$internal$$fulfill(promise, value); } } function $$$internal$$publishRejection(promise) { if (promise._onerror) { promise._onerror(promise._result); } $$$internal$$publish(promise); } function $$$internal$$fulfill(promise, value) { if (promise._state !== $$$internal$$PENDING) { return; } promise._result = value; promise._state = $$$internal$$FULFILLED; if (promise._subscribers.length === 0) { if ($$rsvp$config$$config.instrument) { $$instrument$$default('fulfilled', promise); } } else { $$rsvp$config$$config.async($$$internal$$publish, promise); } } function $$$internal$$reject(promise, reason) { if (promise._state !== $$$internal$$PENDING) { return; } promise._state = $$$internal$$REJECTED; promise._result = reason; $$rsvp$config$$config.async($$$internal$$publishRejection, promise); } function $$$internal$$subscribe(parent, child, onFulfillment, onRejection) { var subscribers = parent._subscribers; var length = subscribers.length; parent._onerror = null; subscribers[length] = child; subscribers[length + $$$internal$$FULFILLED] = onFulfillment; subscribers[length + $$$internal$$REJECTED] = onRejection; if (length === 0 && parent._state) { $$rsvp$config$$config.async($$$internal$$publish, parent); } } function $$$internal$$publish(promise) { var subscribers = promise._subscribers; var settled = promise._state; if ($$rsvp$config$$config.instrument) { $$instrument$$default(settled === $$$internal$$FULFILLED ? 'fulfilled' : 'rejected', promise); } if (subscribers.length === 0) { return; } var child, callback, detail = promise._result; for (var i = 0; i < subscribers.length; i += 3) { child = subscribers[i]; callback = subscribers[i + settled]; if (child) { $$$internal$$invokeCallback(settled, child, callback, detail); } else { callback(detail); } } promise._subscribers.length = 0; } function $$$internal$$ErrorObject() { this.error = null; } var $$$internal$$TRY_CATCH_ERROR = new $$$internal$$ErrorObject(); function $$$internal$$tryCatch(callback, detail) { try { return callback(detail); } catch(e) { $$$internal$$TRY_CATCH_ERROR.error = e; return $$$internal$$TRY_CATCH_ERROR; } } function $$$internal$$invokeCallback(settled, promise, callback, detail) { var hasCallback = $$utils$$isFunction(callback), value, error, succeeded, failed; if (hasCallback) { value = $$$internal$$tryCatch(callback, detail); if (value === $$$internal$$TRY_CATCH_ERROR) { failed = true; error = value.error; value = null; } else { succeeded = true; } if (promise === value) { $$$internal$$reject(promise, new TypeError('A promises callback cannot return that same promise.')); return; } } else { value = detail; succeeded = true; } if (promise._state !== $$$internal$$PENDING) { // noop } else if (hasCallback && succeeded) { $$$internal$$resolve(promise, value); } else if (failed) { $$$internal$$reject(promise, error); } else if (settled === $$$internal$$FULFILLED) { $$$internal$$fulfill(promise, value); } else if (settled === $$$internal$$REJECTED) { $$$internal$$reject(promise, value); } } function $$$internal$$initializePromise(promise, resolver) { try { resolver(function resolvePromise(value){ $$$internal$$resolve(promise, value); }, function rejectPromise(reason) { $$$internal$$reject(promise, reason); }); } catch(e) { $$$internal$$reject(promise, e); } } function $$enumerator$$makeSettledResult(state, position, value) { if (state === $$$internal$$FULFILLED) { return { state: 'fulfilled', value: value }; } else { return { state: 'rejected', reason: value }; } } function $$enumerator$$Enumerator(Constructor, input, abortOnReject, label) { this._instanceConstructor = Constructor; this.promise = new Constructor($$$internal$$noop, label); this._abortOnReject = abortOnReject; if (this._validateInput(input)) { this._input = input; this.length = input.length; this._remaining = input.length; this._init(); if (this.length === 0) { $$$internal$$fulfill(this.promise, this._result); } else { this.length = this.length || 0; this._enumerate(); if (this._remaining === 0) { $$$internal$$fulfill(this.promise, this._result); } } } else { $$$internal$$reject(this.promise, this._validationError()); } } $$enumerator$$Enumerator.prototype._validateInput = function(input) { return $$utils$$isArray(input); }; $$enumerator$$Enumerator.prototype._validationError = function() { return new Error('Array Methods must be provided an Array'); }; $$enumerator$$Enumerator.prototype._init = function() { this._result = new Array(this.length); }; var $$enumerator$$default = $$enumerator$$Enumerator; $$enumerator$$Enumerator.prototype._enumerate = function() { var length = this.length; var promise = this.promise; var input = this._input; for (var i = 0; promise._state === $$$internal$$PENDING && i < length; i++) { this._eachEntry(input[i], i); } }; $$enumerator$$Enumerator.prototype._eachEntry = function(entry, i) { var c = this._instanceConstructor; if ($$utils$$isMaybeThenable(entry)) { if (entry.constructor === c && entry._state !== $$$internal$$PENDING) { entry._onerror = null; this._settledAt(entry._state, i, entry._result); } else { this._willSettleAt(c.resolve(entry), i); } } else { this._remaining--; this._result[i] = this._makeResult($$$internal$$FULFILLED, i, entry); } }; $$enumerator$$Enumerator.prototype._settledAt = function(state, i, value) { var promise = this.promise; if (promise._state === $$$internal$$PENDING) { this._remaining--; if (this._abortOnReject && state === $$$internal$$REJECTED) { $$$internal$$reject(promise, value); } else { this._result[i] = this._makeResult(state, i, value); } } if (this._remaining === 0) { $$$internal$$fulfill(promise, this._result); } }; $$enumerator$$Enumerator.prototype._makeResult = function(state, i, value) { return value; }; $$enumerator$$Enumerator.prototype._willSettleAt = function(promise, i) { var enumerator = this; $$$internal$$subscribe(promise, undefined, function(value) { enumerator._settledAt($$$internal$$FULFILLED, i, value); }, function(reason) { enumerator._settledAt($$$internal$$REJECTED, i, reason); }); }; var $$promise$all$$default = function all(entries, label) { return new $$enumerator$$default(this, entries, true /* abort on reject */, label).promise; }; var $$promise$race$$default = function race(entries, label) { /*jshint validthis:true */ var Constructor = this; var promise = new Constructor($$$internal$$noop, label); if (!$$utils$$isArray(entries)) { $$$internal$$reject(promise, new TypeError('You must pass an array to race.')); return promise; } var length = entries.length; function onFulfillment(value) { $$$internal$$resolve(promise, value); } function onRejection(reason) { $$$internal$$reject(promise, reason); } for (var i = 0; promise._state === $$$internal$$PENDING && i < length; i++) { $$$internal$$subscribe(Constructor.resolve(entries[i]), undefined, onFulfillment, onRejection); } return promise; }; var $$promise$resolve$$default = function resolve(object, label) { /*jshint validthis:true */ var Constructor = this; if (object && typeof object === 'object' && object.constructor === Constructor) { return object; } var promise = new Constructor($$$internal$$noop, label); $$$internal$$resolve(promise, object); return promise; }; var $$promise$reject$$default = function reject(reason, label) { /*jshint validthis:true */ var Constructor = this; var promise = new Constructor($$$internal$$noop, label); $$$internal$$reject(promise, reason); return promise; }; var $$rsvp$promise$$guidKey = 'rsvp_' + $$utils$$now() + '-'; var $$rsvp$promise$$counter = 0; function $$rsvp$promise$$needsResolver() { throw new TypeError('You must pass a resolver function as the first argument to the promise constructor'); } function $$rsvp$promise$$needsNew() { throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function."); } var $$rsvp$promise$$default = $$rsvp$promise$$Promise; /** Promise objects represent the eventual result of an asynchronous operation. The primary way of interacting with a promise is through its `then` method, which registers callbacks to receive either a promise’s eventual value or the reason why the promise cannot be fulfilled. Terminology ----------- - `promise` is an object or function with a `then` method whose behavior conforms to this specification. - `thenable` is an object or function that defines a `then` method. - `value` is any legal JavaScript value (including undefined, a thenable, or a promise). - `exception` is a value that is thrown using the throw statement. - `reason` is a value that indicates why a promise was rejected. - `settled` the final resting state of a promise, fulfilled or rejected. A promise can be in one of three states: pending, fulfilled, or rejected. Promises that are fulfilled have a fulfillment value and are in the fulfilled state. Promises that are rejected have a rejection reason and are in the rejected state. A fulfillment value is never a thenable. Promises can also be said to *resolve* a value. If this value is also a promise, then the original promise's settled state will match the value's settled state. So a promise that *resolves* a promise that rejects will itself reject, and a promise that *resolves* a promise that fulfills will itself fulfill. Basic Usage: ------------ ```js var promise = new Promise(function(resolve, reject) { // on success resolve(value); // on failure reject(reason); }); promise.then(function(value) { // on fulfillment }, function(reason) { // on rejection }); ``` Advanced Usage: --------------- Promises shine when abstracting away asynchronous interactions such as `XMLHttpRequest`s. ```js function getJSON(url) { return new Promise(function(resolve, reject){ var xhr = new XMLHttpRequest(); xhr.open('GET', url); xhr.onreadystatechange = handler; xhr.responseType = 'json'; xhr.setRequestHeader('Accept', 'application/json'); xhr.send(); function handler() { if (this.readyState === this.DONE) { if (this.status === 200) { resolve(this.response); } else { reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']')); } } }; }); } getJSON('/posts.json').then(function(json) { // on fulfillment }, function(reason) { // on rejection }); ``` Unlike callbacks, promises are great composable primitives. ```js Promise.all([ getJSON('/posts'), getJSON('/comments') ]).then(function(values){ values[0] // => postsJSON values[1] // => commentsJSON return values; }); ``` @class RSVP.Promise @param {function} resolver @param {String} label optional string for labeling the promise. Useful for tooling. @constructor */ function $$rsvp$promise$$Promise(resolver, label) { this._id = $$rsvp$promise$$counter++; this._label = label; this._state = undefined; this._result = undefined; this._subscribers = []; if ($$rsvp$config$$config.instrument) { $$instrument$$default('created', this); } if ($$$internal$$noop !== resolver) { if (!$$utils$$isFunction(resolver)) { $$rsvp$promise$$needsResolver(); } if (!(this instanceof $$rsvp$promise$$Promise)) { $$rsvp$promise$$needsNew(); } $$$internal$$initializePromise(this, resolver); } } // deprecated $$rsvp$promise$$Promise.cast = $$promise$resolve$$default; $$rsvp$promise$$Promise.all = $$promise$all$$default; $$rsvp$promise$$Promise.race = $$promise$race$$default; $$rsvp$promise$$Promise.resolve = $$promise$resolve$$default; $$rsvp$promise$$Promise.reject = $$promise$reject$$default; $$rsvp$promise$$Promise.prototype = { constructor: $$rsvp$promise$$Promise, _guidKey: $$rsvp$promise$$guidKey, _onerror: function (reason) { $$rsvp$config$$config.trigger('error', reason); }, /** The primary way of interacting with a promise is through its `then` method, which registers callbacks to receive either a promise's eventual value or the reason why the promise cannot be fulfilled. ```js findUser().then(function(user){ // user is available }, function(reason){ // user is unavailable, and you are given the reason why }); ``` Chaining -------- The return value of `then` is itself a promise. This second, 'downstream' promise is resolved with the return value of the first promise's fulfillment or rejection handler, or rejected if the handler throws an exception. ```js findUser().then(function (user) { return user.name; }, function (reason) { return 'default name'; }).then(function (userName) { // If `findUser` fulfilled, `userName` will be the user's name, otherwise it // will be `'default name'` }); findUser().then(function (user) { throw new Error('Found user, but still unhappy'); }, function (reason) { throw new Error('`findUser` rejected and we're unhappy'); }).then(function (value) { // never reached }, function (reason) { // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'. // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'. }); ``` If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream. ```js findUser().then(function (user) { throw new PedagogicalException('Upstream error'); }).then(function (value) { // never reached }).then(function (value) { // never reached }, function (reason) { // The `PedgagocialException` is propagated all the way down to here }); ``` Assimilation ------------ Sometimes the value you want to propagate to a downstream promise can only be retrieved asynchronously. This can be achieved by returning a promise in the fulfillment or rejection handler. The downstream promise will then be pending until the returned promise is settled. This is called *assimilation*. ```js findUser().then(function (user) { return findCommentsByAuthor(user); }).then(function (comments) { // The user's comments are now available }); ``` If the assimliated promise rejects, then the downstream promise will also reject. ```js findUser().then(function (user) { return findCommentsByAuthor(user); }).then(function (comments) { // If `findCommentsByAuthor` fulfills, we'll have the value here }, function (reason) { // If `findCommentsByAuthor` rejects, we'll have the reason here }); ``` Simple Example -------------- Synchronous Example ```javascript var result; try { result = findResult(); // success } catch(reason) { // failure } ``` Errback Example ```js findResult(function(result, err){ if (err) { // failure } else { // success } }); ``` Promise Example; ```javascript findResult().then(function(result){ // success }, function(reason){ // failure }); ``` Advanced Example -------------- Synchronous Example ```javascript var author, books; try { author = findAuthor(); books = findBooksByAuthor(author); // success } catch(reason) { // failure } ``` Errback Example ```js function foundBooks(books) { } function failure(reason) { } findAuthor(function(author, err){ if (err) { failure(err); // failure } else { try { findBoooksByAuthor(author, function(books, err) { if (err) { failure(err); } else { try { foundBooks(books); } catch(reason) { failure(reason); } } }); } catch(error) { failure(err); } // success } }); ``` Promise Example; ```javascript findAuthor(). then(findBooksByAuthor). then(function(books){ // found books }).catch(function(reason){ // something went wrong }); ``` @method then @param {Function} onFulfilled @param {Function} onRejected @param {String} label optional string for labeling the promise. Useful for tooling. @return {Promise} */ then: function(onFulfillment, onRejection, label) { var parent = this; var state = parent._state; if (state === $$$internal$$FULFILLED && !onFulfillment || state === $$$internal$$REJECTED && !onRejection) { if ($$rsvp$config$$config.instrument) { $$instrument$$default('chained', this, this); } return this; } parent._onerror = null; var child = new this.constructor($$$internal$$noop, label); var result = parent._result; if ($$rsvp$config$$config.instrument) { $$instrument$$default('chained', parent, child); } if (state) { var callback = arguments[state - 1]; $$rsvp$config$$config.async(function(){ $$$internal$$invokeCallback(state, child, callback, result); }); } else { $$$internal$$subscribe(parent, child, onFulfillment, onRejection); } return child; }, /** `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same as the catch block of a try/catch statement. ```js function findAuthor(){ throw new Error('couldn't find that author'); } // synchronous try { findAuthor(); } catch(reason) { // something went wrong } // async with promises findAuthor().catch(function(reason){ // something went wrong }); ``` @method catch @param {Function} onRejection @param {String} label optional string for labeling the promise. Useful for tooling. @return {Promise} */ 'catch': function(onRejection, label) { return this.then(null, onRejection, label); }, /** `finally` will be invoked regardless of the promise's fate just as native try/catch/finally behaves Synchronous example: ```js findAuthor() { if (Math.random() > 0.5) { throw new Error(); } return new Author(); } try { return findAuthor(); // succeed or fail } catch(error) { return findOtherAuther(); } finally { // always runs // doesn't affect the return value } ``` Asynchronous example: ```js findAuthor().catch(function(reason){ return findOtherAuther(); }).finally(function(){ // author was either found, or not }); ``` @method finally @param {Function} callback @param {String} label optional string for labeling the promise. Useful for tooling. @return {Promise} */ 'finally': function(callback, label) { var constructor = this.constructor; return this.then(function(value) { return constructor.resolve(callback()).then(function(){ return value; }); }, function(reason) { return constructor.resolve(callback()).then(function(){ throw reason; }); }, label); } }; function $$rsvp$node$$Result() { this.value = undefined; } var $$rsvp$node$$ERROR = new $$rsvp$node$$Result(); var $$rsvp$node$$GET_THEN_ERROR = new $$rsvp$node$$Result(); function $$rsvp$node$$getThen(obj) { try { return obj.then; } catch(error) { $$rsvp$node$$ERROR.value= error; return $$rsvp$node$$ERROR; } } function $$rsvp$node$$tryApply(f, s, a) { try { f.apply(s, a); } catch(error) { $$rsvp$node$$ERROR.value = error; return $$rsvp$node$$ERROR; } } function $$rsvp$node$$makeObject(_, argumentNames) { var obj = {}; var name; var i; var length = _.length; var args = new Array(length); for (var x = 0; x < length; x++) { args[x] = _[x]; } for (i = 0; i < argumentNames.length; i++) { name = argumentNames[i]; obj[name] = args[i + 1]; } return obj; } function $$rsvp$node$$arrayResult(_) { var length = _.length; var args = new Array(length - 1); for (var i = 1; i < length; i++) { args[i - 1] = _[i]; } return args; } function $$rsvp$node$$wrapThenable(then, promise) { return { then: function(onFulFillment, onRejection) { return then.call(promise, onFulFillment, onRejection); } }; } var $$rsvp$node$$default = function denodeify(nodeFunc, options) { var fn = function() { var self = this; var l = arguments.length; var args = new Array(l + 1); var arg; var promiseInput = false; for (var i = 0; i < l; ++i) { arg = arguments[i]; if (!promiseInput) { // TODO: clean this up promiseInput = $$rsvp$node$$needsPromiseInput(arg); if (promiseInput === $$rsvp$node$$GET_THEN_ERROR) { var p = new $$rsvp$promise$$default($$$internal$$noop); $$$internal$$reject(p, $$rsvp$node$$GET_THEN_ERROR.value); return p; } else if (promiseInput && promiseInput !== true) { arg = $$rsvp$node$$wrapThenable(promiseInput, arg); } } args[i] = arg; } var promise = new $$rsvp$promise$$default($$$internal$$noop); args[l] = function(err, val) { if (err) $$$internal$$reject(promise, err); else if (options === undefined) $$$internal$$resolve(promise, val); else if (options === true) $$$internal$$resolve(promise, $$rsvp$node$$arrayResult(arguments)); else if ($$utils$$isArray(options)) $$$internal$$resolve(promise, $$rsvp$node$$makeObject(arguments, options)); else $$$internal$$resolve(promise, val); }; if (promiseInput) { return $$rsvp$node$$handlePromiseInput(promise, args, nodeFunc, self); } else { return $$rsvp$node$$handleValueInput(promise, args, nodeFunc, self); } }; fn.__proto__ = nodeFunc; return fn; }; function $$rsvp$node$$handleValueInput(promise, args, nodeFunc, self) { var result = $$rsvp$node$$tryApply(nodeFunc, self, args); if (result === $$rsvp$node$$ERROR) { $$$internal$$reject(promise, result.value); } return promise; } function $$rsvp$node$$handlePromiseInput(promise, args, nodeFunc, self){ return $$rsvp$promise$$default.all(args).then(function(args){ var result = $$rsvp$node$$tryApply(nodeFunc, self, args); if (result === $$rsvp$node$$ERROR) { $$$internal$$reject(promise, result.value); } return promise; }); } function $$rsvp$node$$needsPromiseInput(arg) { if (arg && typeof arg === 'object') { if (arg.constructor === $$rsvp$promise$$default) { return true; } else { return $$rsvp$node$$getThen(arg); } } else { return false; } } var $$rsvp$all$$default = function all(array, label) { return $$rsvp$promise$$default.all(array, label); }; function $$rsvp$all$settled$$AllSettled(Constructor, entries, label) { this._superConstructor(Constructor, entries, false /* don't abort on reject */, label); } $$rsvp$all$settled$$AllSettled.prototype = $$utils$$o_create($$enumerator$$default.prototype); $$rsvp$all$settled$$AllSettled.prototype._superConstructor = $$enumerator$$default; $$rsvp$all$settled$$AllSettled.prototype._makeResult = $$enumerator$$makeSettledResult; $$rsvp$all$settled$$AllSettled.prototype._validationError = function() { return new Error('allSettled must be called with an array'); }; var $$rsvp$all$settled$$default = function allSettled(entries, label) { return new $$rsvp$all$settled$$AllSettled($$rsvp$promise$$default, entries, label).promise; }; var $$rsvp$race$$default = function race(array, label) { return $$rsvp$promise$$default.race(array, label); }; function $$promise$hash$$PromiseHash(Constructor, object, label) { this._superConstructor(Constructor, object, true, label); } var $$promise$hash$$default = $$promise$hash$$PromiseHash; $$promise$hash$$PromiseHash.prototype = $$utils$$o_create($$enumerator$$default.prototype); $$promise$hash$$PromiseHash.prototype._superConstructor = $$enumerator$$default; $$promise$hash$$PromiseHash.prototype._init = function() { this._result = {}; }; $$promise$hash$$PromiseHash.prototype._validateInput = function(input) { return input && typeof input === 'object'; }; $$promise$hash$$PromiseHash.prototype._validationError = function() { return new Error('Promise.hash must be called with an object'); }; $$promise$hash$$PromiseHash.prototype._enumerate = function() { var promise = this.promise; var input = this._input; var results = []; for (var key in input) { if (promise._state === $$$internal$$PENDING && input.hasOwnProperty(key)) { results.push({ position: key, entry: input[key] }); } } var length = results.length; this._remaining = length; var result; for (var i = 0; promise._state === $$$internal$$PENDING && i < length; i++) { result = results[i]; this._eachEntry(result.entry, result.position); } }; var $$rsvp$hash$$default = function hash(object, label) { return new $$promise$hash$$default($$rsvp$promise$$default, object, label).promise; }; function $$rsvp$hash$settled$$HashSettled(Constructor, object, label) { this._superConstructor(Constructor, object, false, label); } $$rsvp$hash$settled$$HashSettled.prototype = $$utils$$o_create($$promise$hash$$default.prototype); $$rsvp$hash$settled$$HashSettled.prototype._superConstructor = $$enumerator$$default; $$rsvp$hash$settled$$HashSettled.prototype._makeResult = $$enumerator$$makeSettledResult; $$rsvp$hash$settled$$HashSettled.prototype._validationError = function() { return new Error('hashSettled must be called with an object'); }; var $$rsvp$hash$settled$$default = function hashSettled(object, label) { return new $$rsvp$hash$settled$$HashSettled($$rsvp$promise$$default, object, label).promise; }; var $$rsvp$rethrow$$default = function rethrow(reason) { setTimeout(function() { throw reason; }); throw reason; }; var $$rsvp$defer$$default = function defer(label) { var deferred = { }; deferred.promise = new $$rsvp$promise$$default(function(resolve, reject) { deferred.resolve = resolve; deferred.reject = reject; }, label); return deferred; }; var $$rsvp$map$$default = function map(promises, mapFn, label) { return $$rsvp$promise$$default.all(promises, label).then(function(values) { if (!$$utils$$isFunction(mapFn)) { throw new TypeError("You must pass a function as map's second argument."); } var length = values.length; var results = new Array(length); for (var i = 0; i < length; i++) { results[i] = mapFn(values[i]); } return $$rsvp$promise$$default.all(results, label); }); }; var $$rsvp$resolve$$default = function resolve(value, label) { return $$rsvp$promise$$default.resolve(value, label); }; var $$rsvp$reject$$default = function reject(reason, label) { return $$rsvp$promise$$default.reject(reason, label); }; var $$rsvp$filter$$default = function filter(promises, filterFn, label) { return $$rsvp$promise$$default.all(promises, label).then(function(values) { if (!$$utils$$isFunction(filterFn)) { throw new TypeError("You must pass a function as filter's second argument."); } var length = values.length; var filtered = new Array(length); for (var i = 0; i < length; i++) { filtered[i] = filterFn(values[i]); } return $$rsvp$promise$$default.all(filtered, label).then(function(filtered) { var results = new Array(length); var newLength = 0; for (var i = 0; i < length; i++) { if (filtered[i]) { results[newLength] = values[i]; newLength++; } } results.length = newLength; return results; }); }); }; var $$rsvp$asap$$len = 0; var $$rsvp$asap$$default = function asap(callback, arg) { $$rsvp$asap$$queue[$$rsvp$asap$$len] = callback; $$rsvp$asap$$queue[$$rsvp$asap$$len + 1] = arg; $$rsvp$asap$$len += 2; if ($$rsvp$asap$$len === 2) { // If len is 1, that means that we need to schedule an async flush. // If additional callbacks are queued before the queue is flushed, they // will be processed by this flush that we are scheduling. $$rsvp$asap$$scheduleFlush(); } }; var $$rsvp$asap$$browserGlobal = (typeof window !== 'undefined') ? window : {}; var $$rsvp$asap$$BrowserMutationObserver = $$rsvp$asap$$browserGlobal.MutationObserver || $$rsvp$asap$$browserGlobal.WebKitMutationObserver; // test for web worker but not in IE10 var $$rsvp$asap$$isWorker = typeof Uint8ClampedArray !== 'undefined' && typeof importScripts !== 'undefined' && typeof MessageChannel !== 'undefined'; // node function $$rsvp$asap$$useNextTick() { return function() { process.nextTick($$rsvp$asap$$flush); }; } function $$rsvp$asap$$useMutationObserver() { var iterations = 0; var observer = new $$rsvp$asap$$BrowserMutationObserver($$rsvp$asap$$flush); var node = document.createTextNode(''); observer.observe(node, { characterData: true }); return function() { node.data = (iterations = ++iterations % 2); }; } // web worker function $$rsvp$asap$$useMessageChannel() { var channel = new MessageChannel(); channel.port1.onmessage = $$rsvp$asap$$flush; return function () { channel.port2.postMessage(0); }; } function $$rsvp$asap$$useSetTimeout() { return function() { setTimeout($$rsvp$asap$$flush, 1); }; } var $$rsvp$asap$$queue = new Array(1000); function $$rsvp$asap$$flush() { for (var i = 0; i < $$rsvp$asap$$len; i+=2) { var callback = $$rsvp$asap$$queue[i]; var arg = $$rsvp$asap$$queue[i+1]; callback(arg); $$rsvp$asap$$queue[i] = undefined; $$rsvp$asap$$queue[i+1] = undefined; } $$rsvp$asap$$len = 0; } var $$rsvp$asap$$scheduleFlush; // Decide what async method to use to triggering processing of queued callbacks: if (typeof process !== 'undefined' && {}.toString.call(process) === '[object process]') { $$rsvp$asap$$scheduleFlush = $$rsvp$asap$$useNextTick(); } else if ($$rsvp$asap$$BrowserMutationObserver) { $$rsvp$asap$$scheduleFlush = $$rsvp$asap$$useMutationObserver(); } else if ($$rsvp$asap$$isWorker) { $$rsvp$asap$$scheduleFlush = $$rsvp$asap$$useMessageChannel(); } else { $$rsvp$asap$$scheduleFlush = $$rsvp$asap$$useSetTimeout(); } // default async is asap; $$rsvp$config$$config.async = $$rsvp$asap$$default; var $$rsvp$$cast = $$rsvp$resolve$$default; function $$rsvp$$async(callback, arg) { $$rsvp$config$$config.async(callback, arg); } function $$rsvp$$on() { $$rsvp$config$$config.on.apply($$rsvp$config$$config, arguments); } function $$rsvp$$off() { $$rsvp$config$$config.off.apply($$rsvp$config$$config, arguments); } // Set up instrumentation through `window.__PROMISE_INTRUMENTATION__` if (typeof window !== 'undefined' && typeof window['__PROMISE_INSTRUMENTATION__'] === 'object') { var $$rsvp$$callbacks = window['__PROMISE_INSTRUMENTATION__']; $$rsvp$config$$configure('instrument', true); for (var $$rsvp$$eventName in $$rsvp$$callbacks) { if ($$rsvp$$callbacks.hasOwnProperty($$rsvp$$eventName)) { $$rsvp$$on($$rsvp$$eventName, $$rsvp$$callbacks[$$rsvp$$eventName]); } } } var rsvp$umd$$RSVP = { 'race': $$rsvp$race$$default, 'Promise': $$rsvp$promise$$default, 'allSettled': $$rsvp$all$settled$$default, 'hash': $$rsvp$hash$$default, 'hashSettled': $$rsvp$hash$settled$$default, 'denodeify': $$rsvp$node$$default, 'on': $$rsvp$$on, 'off': $$rsvp$$off, 'map': $$rsvp$map$$default, 'filter': $$rsvp$filter$$default, 'resolve': $$rsvp$resolve$$default, 'reject': $$rsvp$reject$$default, 'all': $$rsvp$all$$default, 'rethrow': $$rsvp$rethrow$$default, 'defer': $$rsvp$defer$$default, 'EventTarget': $$rsvp$events$$default, 'configure': $$rsvp$config$$configure, 'async': $$rsvp$$async }; /* global define:true module:true window: true */ if (typeof define === 'function' && define.amd) { define(function() { return rsvp$umd$$RSVP; }); } else if (typeof module !== 'undefined' && module.exports) { module.exports = rsvp$umd$$RSVP; } else if (typeof this !== 'undefined') { this['RSVP'] = rsvp$umd$$RSVP; }
}).call(this);