dist/ember-runtime.js in ember-source-2.10.2 vs dist/ember-runtime.js in ember-source-2.11.0.beta.2

- old
+ new

@@ -4,15 +4,14 @@ * @copyright Copyright 2011-2016 Tilde Inc. and contributors * Portions Copyright 2006-2011 Strobe Inc. * Portions Copyright 2008-2011 Apple Inc. All rights reserved. * @license Licensed under MIT license * See https://raw.github.com/emberjs/ember.js/master/LICENSE - * @version 2.10.2 + * @version 2.11.0-beta.2 */ var enifed, requireModule, Ember; -var mainContext = this; (function() { var isNode = typeof window === 'undefined' && typeof process !== 'undefined' && {}.toString.call(process) === '[object process]'; @@ -110,12 +109,10 @@ enifed = Ember.__loader.define; requireModule = Ember.__loader.require; } })(); -var babelHelpers; - function inherits(subClass, superClass) { subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, @@ -1459,11 +1456,11 @@ } else { var injections = injectionsFor(container, fullName); var factoryInjections = factoryInjectionsFor(container, fullName); var cacheable = !areInjectionsDynamic(injections) && !areInjectionsDynamic(factoryInjections); - factoryInjections._toString = registry.makeToString(factory, fullName); + factoryInjections[_emberUtils.NAME_KEY] = registry.makeToString(factory, fullName); var injectedFactory = factory.extend(injections); // TODO - remove all `container` injections when Ember reaches v3.0.0 injectDeprecatedContainer(injectedFactory.prototype, container); @@ -2786,12 +2783,10 @@ 'use strict'; exports.default = alias; exports.AliasedProperty = AliasedProperty; - var CONSUMED = {}; - function alias(altKey) { return new AliasedProperty(altKey); } function AliasedProperty(altKey) { @@ -2808,34 +2803,32 @@ if (meta.peekWatching(keyName)) { _emberMetalDependent_keys.addDependentKeys(this, obj, keyName, meta); } }; - AliasedProperty.prototype.teardown = function (obj, keyName) { + AliasedProperty.prototype._addDependentKeyIfMissing = function (obj, keyName) { var meta = _emberMetalMeta.meta(obj); - if (meta.peekWatching(keyName)) { - _emberMetalDependent_keys.removeDependentKeys(this, obj, keyName, meta); + if (!meta.peekDeps(this.altKey, keyName)) { + _emberMetalDependent_keys.addDependentKeys(this, obj, keyName, meta); } }; - AliasedProperty.prototype.willWatch = function (obj, keyName) { - _emberMetalDependent_keys.addDependentKeys(this, obj, keyName, _emberMetalMeta.meta(obj)); + AliasedProperty.prototype._removeDependentKeyIfAdded = function (obj, keyName) { + var meta = _emberMetalMeta.meta(obj); + if (meta.peekDeps(this.altKey, keyName)) { + _emberMetalDependent_keys.removeDependentKeys(this, obj, keyName, meta); + } }; - AliasedProperty.prototype.didUnwatch = function (obj, keyName) { - _emberMetalDependent_keys.removeDependentKeys(this, obj, keyName, _emberMetalMeta.meta(obj)); - }; + AliasedProperty.prototype.willWatch = AliasedProperty.prototype._addDependentKeyIfMissing; + AliasedProperty.prototype.didUnwatch = AliasedProperty.prototype._removeDependentKeyIfAdded; + AliasedProperty.prototype.teardown = AliasedProperty.prototype._removeDependentKeyIfAdded; AliasedProperty.prototype.get = function AliasedProperty_get(obj, keyName) { - var ret = _emberMetalProperty_get.get(obj, this.altKey); - var meta = _emberMetalMeta.meta(obj); - var cache = meta.writableCache(); - if (cache[keyName] !== CONSUMED) { - cache[keyName] = CONSUMED; - _emberMetalDependent_keys.addDependentKeys(this, obj, keyName, meta); - } - return ret; + this._addDependentKeyIfMissing(obj, keyName); + + return _emberMetalProperty_get.get(obj, this.altKey); }; AliasedProperty.prototype.set = function AliasedProperty_set(obj, keyName, value) { return _emberMetalProperty_set.set(obj, this.altKey, value); }; @@ -5342,11 +5335,10 @@ exports.addObserver = _emberMetalObserver.addObserver; exports.observersFor = _emberMetalObserver.observersFor; exports.removeObserver = _emberMetalObserver.removeObserver; exports._addBeforeObserver = _emberMetalObserver._addBeforeObserver; exports._removeBeforeObserver = _emberMetalObserver._removeBeforeObserver; - exports.NAME_KEY = _emberMetalMixin.NAME_KEY; exports.Mixin = _emberMetalMixin.Mixin; exports.aliasMethod = _emberMetalMixin.aliasMethod; exports._immediateObserver = _emberMetalMixin._immediateObserver; exports._beforeObserver = _emberMetalMixin._beforeObserver; exports.mixin = _emberMetalMixin.mixin; @@ -7381,24 +7373,36 @@ return _emberUtils.wrap(method, superMethod); } function applyConcatenatedProperties(obj, key, value, values) { var baseValue = values[key] || obj[key]; + var ret = undefined; if (baseValue) { if ('function' === typeof baseValue.concat) { if (value === null || value === undefined) { - return baseValue; + ret = baseValue; } else { - return baseValue.concat(value); + ret = baseValue.concat(value); } } else { - return _emberUtils.makeArray(baseValue).concat(value); + ret = _emberUtils.makeArray(baseValue).concat(value); } } else { - return _emberUtils.makeArray(value); + ret = _emberUtils.makeArray(value); } + + _emberMetalDebug.runInDebug(function () { + // it is possible to use concatenatedProperties with strings (which cannot be frozen) + // only freeze objects... + if (typeof ret === 'object' && ret !== null) { + // prevent mutating `concatenatedProperties` array after it is applied + Object.freeze(ret); + } + }); + + return ret; } function applyMergedProperties(obj, key, value, values) { var baseValue = values[key] || obj[key]; @@ -7670,13 +7674,10 @@ applyMixin(obj, args, false); return obj; } - var NAME_KEY = _emberUtils.GUID_KEY + '_name'; - - exports.NAME_KEY = NAME_KEY; /** The `Ember.Mixin` class allows you to create mixins, whose properties can be added to other classes. For instance, ```javascript @@ -7755,11 +7756,11 @@ this.mixins = undefined; } this.ownerConstructor = undefined; this._without = undefined; this[_emberUtils.GUID_KEY] = null; - this[NAME_KEY] = null; + this[_emberUtils.NAME_KEY] = null; _emberMetalDebug.debugSeal(this); } Mixin._apply = applyMixin; @@ -10142,11 +10143,11 @@ label = parts.join(); } else { label = 'the same value'; } - return 'You modified ' + parts.join('.') + ' twice on ' + object + ' in a single render. This was unreliable and slow in Ember 1.x and ' + implication; + return 'You modified ' + label + ' twice on ' + object + ' in a single render. This was unreliable and slow in Ember 1.x and ' + implication; })(), false); shouldReflush = true; } }; @@ -13197,24 +13198,21 @@ send: function (actionName) { for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; } - var target = undefined; - if (this.actions && this.actions[actionName]) { var shouldBubble = this.actions[actionName].apply(this, args) === true; if (!shouldBubble) { return; } } - if (target = _emberMetal.get(this, 'target')) { - var _target; - + var target = _emberMetal.get(this, 'target'); + if (target) { _emberMetal.assert('The `target` for ' + this + ' (' + target + ') does not have a `send` method', typeof target.send === 'function'); - (_target = target).send.apply(_target, arguments); + target.send.apply(target, arguments); } }, willMergeMixin: function (props) { _emberMetal.assert('Specifying `_actions` and `actions` in the same mixin is not supported.', !props.actions || !props._actions); @@ -13631,11 +13629,11 @@ */ /** This returns the objects at the specified indexes, using `objectAt`. ```javascript - let arr = ['a', 'b', 'c', 'd']; + let arr = ['a', 'b', 'c', 'd']; arr.objectsAt([0, 1, 2]); // ['a', 'b', 'c'] arr.objectsAt([2, 3, 4]); // ['c', 'd', undefined] ``` @method objectsAt @param {Array} indexes An array of indexes of items to return. @@ -14571,11 +14569,12 @@ ret = undefined; for (var idx = 0; idx < len && !found; idx++) { next = this.nextObject(idx, last, context); - if (found = callback.call(target, next, idx, this)) { + found = callback.call(target, next, idx, this); + if (found) { ret = next; } last = next; } @@ -17364,11 +17363,11 @@ */ // using ember-metal/lib/main here to ensure that ember-debug is setup // if present - var _Mixin$create; + var _Mixin$create, _ClassMixinProps; var _templateObject = babelHelpers.taggedTemplateLiteralLoose(['.'], ['.']); var schedule = _emberMetal.run.schedule; var applyMixin = _emberMetal.Mixin._apply; @@ -17623,322 +17622,107 @@ CoreObject.PrototypeMixin.ownerConstructor = CoreObject; CoreObject.__super__ = null; - var ClassMixinProps = { + var ClassMixinProps = (_ClassMixinProps = { ClassMixin: _emberMetal.REQUIRED, PrototypeMixin: _emberMetal.REQUIRED, isClass: true, - isMethod: false, - /** - Creates a new subclass. - ```javascript - const Person = Ember.Object.extend({ - say(thing) { - alert(thing); - } - }); - ``` - This defines a new subclass of Ember.Object: `Person`. It contains one method: `say()`. - You can also create a subclass from any existing class by calling its `extend()` method. - For example, you might want to create a subclass of Ember's built-in `Ember.Component` class: - ```javascript - const PersonComponent = Ember.Component.extend({ - tagName: 'li', - classNameBindings: ['isAdministrator'] - }); - ``` - When defining a subclass, you can override methods but still access the - implementation of your parent class by calling the special `_super()` method: - ```javascript - const Person = Ember.Object.extend({ - say(thing) { - var name = this.get('name'); - alert(`${name} says: ${thing}`); - } - }); - const Soldier = Person.extend({ - say(thing) { - this._super(`${thing}, sir!`); - }, - march(numberOfHours) { - alert(`${this.get('name')} marches for ${numberOfHours} hours.`); - } - }); - let yehuda = Soldier.create({ - name: "Yehuda Katz" - }); - yehuda.say("Yes"); // alerts "Yehuda Katz says: Yes, sir!" - ``` - The `create()` on line #17 creates an *instance* of the `Soldier` class. - The `extend()` on line #8 creates a *subclass* of `Person`. Any instance - of the `Person` class will *not* have the `march()` method. - You can also pass `Mixin` classes to add additional properties to the subclass. - ```javascript - const Person = Ember.Object.extend({ - say(thing) { - alert(`${this.get('name')} says: ${thing}`); - } - }); - const SingingMixin = Mixin.create({ - sing(thing){ - alert(`${this.get('name')} sings: la la la ${thing}`); - } - }); - const BroadwayStar = Person.extend(SingingMixin, { - dance() { - alert(`${this.get('name')} dances: tap tap tap tap `); - } - }); - ``` - The `BroadwayStar` class contains three methods: `say()`, `sing()`, and `dance()`. - @method extend - @static - @param {Mixin} [mixins]* One or more Mixin classes - @param {Object} [arguments]* Object containing values to use within the new class - @public - */ - extend: function () { - var Class = makeCtor(); - var proto; - Class.ClassMixin = _emberMetal.Mixin.create(this.ClassMixin); - Class.PrototypeMixin = _emberMetal.Mixin.create(this.PrototypeMixin); + isMethod: false + }, _ClassMixinProps[_emberUtils.NAME_KEY] = null, _ClassMixinProps[_emberUtils.GUID_KEY] = null, _ClassMixinProps.extend = function () { + var Class = makeCtor(); + var proto; + Class.ClassMixin = _emberMetal.Mixin.create(this.ClassMixin); + Class.PrototypeMixin = _emberMetal.Mixin.create(this.PrototypeMixin); - Class.ClassMixin.ownerConstructor = Class; - Class.PrototypeMixin.ownerConstructor = Class; + Class.ClassMixin.ownerConstructor = Class; + Class.PrototypeMixin.ownerConstructor = Class; - reopen.apply(Class.PrototypeMixin, arguments); + reopen.apply(Class.PrototypeMixin, arguments); - Class.superclass = this; - Class.__super__ = this.prototype; + Class.superclass = this; + Class.__super__ = this.prototype; - proto = Class.prototype = Object.create(this.prototype); - proto.constructor = Class; - _emberUtils.generateGuid(proto); - _emberMetal.meta(proto).proto = proto; // this will disable observers on prototype + proto = Class.prototype = Object.create(this.prototype); + proto.constructor = Class; + _emberUtils.generateGuid(proto); + _emberMetal.meta(proto).proto = proto; // this will disable observers on prototype - Class.ClassMixin.apply(Class); - return Class; - }, + Class.ClassMixin.apply(Class); + return Class; + }, _ClassMixinProps.create = function () { + var C = this; - /** - Creates an instance of a class. Accepts either no arguments, or an object - containing values to initialize the newly instantiated object with. - ```javascript - const Person = Ember.Object.extend({ - helloWorld() { - alert(`Hi, my name is ${this.get('name')}`); - } - }); - let tom = Person.create({ - name: 'Tom Dale' - }); - tom.helloWorld(); // alerts "Hi, my name is Tom Dale". - ``` - `create` will call the `init` function if defined during - `Ember.AnyObject.extend` - If no arguments are passed to `create`, it will not set values to the new - instance during initialization: - ```javascript - let noName = Person.create(); - noName.helloWorld(); // alerts undefined - ``` - NOTE: For performance reasons, you cannot declare methods or computed - properties during `create`. You should instead declare methods and computed - properties when using `extend`. - @method create - @static - @param [arguments]* - @public - */ - create: function () { - var C = this; + for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { + args[_key2] = arguments[_key2]; + } - for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { - args[_key2] = arguments[_key2]; + if (args.length > 0) { + this._initProperties(args); + } + return new C(); + }, _ClassMixinProps.reopen = function () { + this.willReopen(); + reopen.apply(this.PrototypeMixin, arguments); + return this; + }, _ClassMixinProps.reopenClass = function () { + reopen.apply(this.ClassMixin, arguments); + applyMixin(this, arguments, false); + return this; + }, _ClassMixinProps.detect = function (obj) { + if ('function' !== typeof obj) { + return false; + } + while (obj) { + if (obj === this) { + return true; } + obj = obj.superclass; + } + return false; + }, _ClassMixinProps.detectInstance = function (obj) { + return obj instanceof this; + }, _ClassMixinProps.metaForProperty = function (key) { + var proto = this.proto(); + var possibleDesc = proto[key]; + var desc = possibleDesc !== null && typeof possibleDesc === 'object' && possibleDesc.isDescriptor ? possibleDesc : undefined; - if (args.length > 0) { - this._initProperties(args); - } - return new C(); - }, + _emberMetal.assert('metaForProperty() could not find a computed property ' + 'with key \'' + key + '\'.', !!desc && desc instanceof _emberMetal.ComputedProperty); + return desc._meta || {}; + }, _ClassMixinProps._computedProperties = _emberMetal.computed(function () { + hasCachedComputedProperties = true; + var proto = this.proto(); + var property; + var properties = []; - /** - Augments a constructor's prototype with additional - properties and functions: - ```javascript - const MyObject = Ember.Object.extend({ - name: 'an object' - }); - o = MyObject.create(); - o.get('name'); // 'an object' - MyObject.reopen({ - say(msg){ - console.log(msg); - } - }) - o2 = MyObject.create(); - o2.say("hello"); // logs "hello" - o.say("goodbye"); // logs "goodbye" - ``` - To add functions and properties to the constructor itself, - see `reopenClass` - @method reopen - @public - */ - reopen: function () { - this.willReopen(); - reopen.apply(this.PrototypeMixin, arguments); - return this; - }, + for (var name in proto) { + property = proto[name]; - /** - Augments a constructor's own properties and functions: - ```javascript - const MyObject = Ember.Object.extend({ - name: 'an object' - }); - MyObject.reopenClass({ - canBuild: false - }); - MyObject.canBuild; // false - o = MyObject.create(); - ``` - In other words, this creates static properties and functions for the class. - These are only available on the class and not on any instance of that class. - ```javascript - const Person = Ember.Object.extend({ - name: "", - sayHello() { - alert("Hello. My name is " + this.get('name')); - } - }); - Person.reopenClass({ - species: "Homo sapiens", - createPerson(newPersonsName){ - return Person.create({ - name:newPersonsName - }); - } - }); - let tom = Person.create({ - name: "Tom Dale" - }); - let yehuda = Person.createPerson("Yehuda Katz"); - tom.sayHello(); // "Hello. My name is Tom Dale" - yehuda.sayHello(); // "Hello. My name is Yehuda Katz" - alert(Person.species); // "Homo sapiens" - ``` - Note that `species` and `createPerson` are *not* valid on the `tom` and `yehuda` - variables. They are only valid on `Person`. - To add functions and properties to instances of - a constructor by extending the constructor's prototype - see `reopen` - @method reopenClass - @public - */ - reopenClass: function () { - reopen.apply(this.ClassMixin, arguments); - applyMixin(this, arguments, false); - return this; - }, - - detect: function (obj) { - if ('function' !== typeof obj) { - return false; + if (property && property.isDescriptor) { + properties.push({ + name: name, + meta: property._meta + }); } - while (obj) { - if (obj === this) { - return true; - } - obj = obj.superclass; - } - return false; - }, + } + return properties; + }).readOnly(), _ClassMixinProps.eachComputedProperty = function (callback, binding) { + var property; + var empty = {}; - detectInstance: function (obj) { - return obj instanceof this; - }, + var properties = _emberMetal.get(this, '_computedProperties'); - /** - In some cases, you may want to annotate computed properties with additional - metadata about how they function or what values they operate on. For - example, computed property functions may close over variables that are then - no longer available for introspection. - You can pass a hash of these values to a computed property like this: - ```javascript - person: Ember.computed(function() { - var personId = this.get('personId'); - return Person.create({ id: personId }); - }).meta({ type: Person }) - ``` - Once you've done this, you can retrieve the values saved to the computed - property from your class like this: - ```javascript - MyClass.metaForProperty('person'); - ``` - This will return the original hash that was passed to `meta()`. - @static - @method metaForProperty - @param key {String} property name - @private - */ - metaForProperty: function (key) { - var proto = this.proto(); - var possibleDesc = proto[key]; - var desc = possibleDesc !== null && typeof possibleDesc === 'object' && possibleDesc.isDescriptor ? possibleDesc : undefined; - - _emberMetal.assert('metaForProperty() could not find a computed property ' + 'with key \'' + key + '\'.', !!desc && desc instanceof _emberMetal.ComputedProperty); - return desc._meta || {}; - }, - - _computedProperties: _emberMetal.computed(function () { - hasCachedComputedProperties = true; - var proto = this.proto(); - var property; - var properties = []; - - for (var name in proto) { - property = proto[name]; - - if (property && property.isDescriptor) { - properties.push({ - name: name, - meta: property._meta - }); - } - } - return properties; - }).readOnly(), - - /** - Iterate over each computed property for the class, passing its name - and any associated metadata (see `metaForProperty`) to the callback. - @static - @method eachComputedProperty - @param {Function} callback - @param {Object} binding - @private - */ - eachComputedProperty: function (callback, binding) { - var property; - var empty = {}; - - var properties = _emberMetal.get(this, '_computedProperties'); - - for (var i = 0; i < properties.length; i++) { - property = properties[i]; - callback.call(binding || this, property.name, property.meta || empty); - } + for (var i = 0; i < properties.length; i++) { + property = properties[i]; + callback.call(binding || this, property.name, property.meta || empty); } - }; + }, _ClassMixinProps); function injectedPropertyAssertion() { _emberMetal.assert('Injected properties are invalid', _emberRuntimeInject.validatePropertyInjections(this)); } @@ -18192,10 +17976,214 @@ ``` @method toString @return {String} string representation @public */ + +/** + Creates a new subclass. + ```javascript + const Person = Ember.Object.extend({ + say(thing) { + alert(thing); + } + }); + ``` + This defines a new subclass of Ember.Object: `Person`. It contains one method: `say()`. + You can also create a subclass from any existing class by calling its `extend()` method. + For example, you might want to create a subclass of Ember's built-in `Ember.Component` class: + ```javascript + const PersonComponent = Ember.Component.extend({ + tagName: 'li', + classNameBindings: ['isAdministrator'] + }); + ``` + When defining a subclass, you can override methods but still access the + implementation of your parent class by calling the special `_super()` method: + ```javascript + const Person = Ember.Object.extend({ + say(thing) { + var name = this.get('name'); + alert(`${name} says: ${thing}`); + } + }); + const Soldier = Person.extend({ + say(thing) { + this._super(`${thing}, sir!`); + }, + march(numberOfHours) { + alert(`${this.get('name')} marches for ${numberOfHours} hours.`); + } + }); + let yehuda = Soldier.create({ + name: "Yehuda Katz" + }); + yehuda.say("Yes"); // alerts "Yehuda Katz says: Yes, sir!" + ``` + The `create()` on line #17 creates an *instance* of the `Soldier` class. + The `extend()` on line #8 creates a *subclass* of `Person`. Any instance + of the `Person` class will *not* have the `march()` method. + You can also pass `Mixin` classes to add additional properties to the subclass. + ```javascript + const Person = Ember.Object.extend({ + say(thing) { + alert(`${this.get('name')} says: ${thing}`); + } + }); + const SingingMixin = Mixin.create({ + sing(thing){ + alert(`${this.get('name')} sings: la la la ${thing}`); + } + }); + const BroadwayStar = Person.extend(SingingMixin, { + dance() { + alert(`${this.get('name')} dances: tap tap tap tap `); + } + }); + ``` + The `BroadwayStar` class contains three methods: `say()`, `sing()`, and `dance()`. + @method extend + @static + @param {Mixin} [mixins]* One or more Mixin classes + @param {Object} [arguments]* Object containing values to use within the new class + @public +*/ + +/** + Creates an instance of a class. Accepts either no arguments, or an object + containing values to initialize the newly instantiated object with. + ```javascript + const Person = Ember.Object.extend({ + helloWorld() { + alert(`Hi, my name is ${this.get('name')}`); + } + }); + let tom = Person.create({ + name: 'Tom Dale' + }); + tom.helloWorld(); // alerts "Hi, my name is Tom Dale". + ``` + `create` will call the `init` function if defined during + `Ember.AnyObject.extend` + If no arguments are passed to `create`, it will not set values to the new + instance during initialization: + ```javascript + let noName = Person.create(); + noName.helloWorld(); // alerts undefined + ``` + NOTE: For performance reasons, you cannot declare methods or computed + properties during `create`. You should instead declare methods and computed + properties when using `extend`. + @method create + @static + @param [arguments]* + @public +*/ + +/** + Augments a constructor's prototype with additional + properties and functions: + ```javascript + const MyObject = Ember.Object.extend({ + name: 'an object' + }); + o = MyObject.create(); + o.get('name'); // 'an object' + MyObject.reopen({ + say(msg){ + console.log(msg); + } + }) + o2 = MyObject.create(); + o2.say("hello"); // logs "hello" + o.say("goodbye"); // logs "goodbye" + ``` + To add functions and properties to the constructor itself, + see `reopenClass` + @method reopen + @public +*/ + +/** + Augments a constructor's own properties and functions: + ```javascript + const MyObject = Ember.Object.extend({ + name: 'an object' + }); + MyObject.reopenClass({ + canBuild: false + }); + MyObject.canBuild; // false + o = MyObject.create(); + ``` + In other words, this creates static properties and functions for the class. + These are only available on the class and not on any instance of that class. + ```javascript + const Person = Ember.Object.extend({ + name: "", + sayHello() { + alert("Hello. My name is " + this.get('name')); + } + }); + Person.reopenClass({ + species: "Homo sapiens", + createPerson(newPersonsName){ + return Person.create({ + name:newPersonsName + }); + } + }); + let tom = Person.create({ + name: "Tom Dale" + }); + let yehuda = Person.createPerson("Yehuda Katz"); + tom.sayHello(); // "Hello. My name is Tom Dale" + yehuda.sayHello(); // "Hello. My name is Yehuda Katz" + alert(Person.species); // "Homo sapiens" + ``` + Note that `species` and `createPerson` are *not* valid on the `tom` and `yehuda` + variables. They are only valid on `Person`. + To add functions and properties to instances of + a constructor by extending the constructor's prototype + see `reopen` + @method reopenClass + @public +*/ + +/** + In some cases, you may want to annotate computed properties with additional + metadata about how they function or what values they operate on. For + example, computed property functions may close over variables that are then + no longer available for introspection. + You can pass a hash of these values to a computed property like this: + ```javascript + person: Ember.computed(function() { + var personId = this.get('personId'); + return Person.create({ id: personId }); + }).meta({ type: Person }) + ``` + Once you've done this, you can retrieve the values saved to the computed + property from your class like this: + ```javascript + MyClass.metaForProperty('person'); + ``` + This will return the original hash that was passed to `meta()`. + @static + @method metaForProperty + @param key {String} property name + @private +*/ + +/** + Iterate over each computed property for the class, passing its name + and any associated metadata (see `metaForProperty`) to the callback. + @static + @method eachComputedProperty + @param {Function} callback + @param {Object} binding + @private +*/ enifed('ember-runtime/system/each_proxy', ['exports', 'ember-utils', 'ember-metal', 'ember-runtime/mixins/array'], function (exports, _emberUtils, _emberMetal, _emberRuntimeMixinsArray) { 'use strict'; exports.default = EachProxy; @@ -18444,11 +18432,11 @@ if (name) { return name; } findNamespaces(); - return this[_emberMetal.NAME_KEY]; + return this[_emberUtils.NAME_KEY]; }, nameClasses: function () { processNamespace([this.toString()], this, {}); }, @@ -18504,14 +18492,14 @@ // the key, so processing `Ember.View` will make the Array // `['Ember', 'View']`. paths[idx] = key; // If we have found an unprocessed class - if (obj && obj.toString === classToString && !obj[_emberMetal.NAME_KEY]) { + if (obj && obj.toString === classToString && !obj[_emberUtils.NAME_KEY]) { // Replace the class' `toString` with the dot-separated path // and set its `NAME_KEY` - obj[_emberMetal.NAME_KEY] = paths.join('.'); + obj[_emberUtils.NAME_KEY] = paths.join('.'); // Support nested namespaces } else if (obj && obj.isNamespace) { // Skip aliased namespaces if (seen[_emberUtils.guidFor(obj)]) { @@ -18553,47 +18541,53 @@ if (!isUppercase(key.charCodeAt(0))) { continue; } var obj = tryIsNamespace(lookup, key); if (obj) { - obj[_emberMetal.NAME_KEY] = key; + obj[_emberUtils.NAME_KEY] = key; } } } function superClassString(mixin) { var superclass = mixin.superclass; if (superclass) { - if (superclass[_emberMetal.NAME_KEY]) { - return superclass[_emberMetal.NAME_KEY]; + if (superclass[_emberUtils.NAME_KEY]) { + return superclass[_emberUtils.NAME_KEY]; } return superClassString(superclass); } } - function classToString() { - if (!searchDisabled && !this[_emberMetal.NAME_KEY]) { - processAllNamespaces(); - } + function calculateToString(target) { + var str = undefined; - var ret = undefined; - - if (this[_emberMetal.NAME_KEY]) { - ret = this[_emberMetal.NAME_KEY]; - } else if (this._toString) { - ret = this._toString; - } else { - var str = superClassString(this); + if (!searchDisabled) { + processAllNamespaces(); + // can also be set by processAllNamespaces + str = target[_emberUtils.NAME_KEY]; if (str) { - ret = '(subclass of ' + str + ')'; + return str; } else { - ret = '(unknown mixin)'; + str = superClassString(target); + str = str ? '(subclass of ' + str + ')' : str; } - this.toString = makeToString(ret); } + if (str) { + return str; + } else { + return '(unknown mixin)'; + } + } - return ret; + function classToString() { + var name = this[_emberUtils.NAME_KEY]; + if (name) { + return name; + } + + return this[_emberUtils.NAME_KEY] = calculateToString(this); } function processAllNamespaces() { var unprocessedNamespaces = !Namespace.PROCESSED; var unprocessedMixins = _emberMetal.hasUnprocessedMixins(); @@ -18614,16 +18608,10 @@ _emberMetal.clearUnprocessedMixins(); } } - function makeToString(ret) { - return function () { - return ret; - }; - } - _emberMetal.Mixin.prototype.toString = classToString; // ES6TODO: altering imported objects. SBB. exports.default = Namespace; }); // Preloaded into namespaces @@ -19411,2511 +19399,2538 @@ exports.default = { "features-stripped-test": false, "ember-libraries-isregistered": false, "ember-runtime-computed-uniq-by": true, "ember-improved-instrumentation": false, "ember-runtime-enumerable-includes": true, "ember-string-ishtmlsafe": true, "ember-testing-check-waiters": true, "ember-metal-weakmap": false, "ember-glimmer-allow-backtracking-rerender": false, "ember-testing-resume-test": false, "mandatory-setter": true, "ember-glimmer-detect-backtracking-rerender": true }; }); enifed("ember/version", ["exports"], function (exports) { "use strict"; - exports.default = "2.10.2"; + exports.default = "2.11.0-beta.2"; }); -/*! - * @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.2.1 - */ +enifed('rsvp', ['exports'], function (exports) { + 'use strict'; -enifed('rsvp', ['exports'], function (exports) { 'use strict'; + var _rsvp; -function indexOf(callbacks, callback) { - for (var i=0, l=callbacks.length; i<l; i++) { - if (callbacks[i] === callback) { return i; } + function indexOf(callbacks, callback) { + for (var i = 0, l = callbacks.length; i < l; i++) { + if (callbacks[i] === callback) { + return i; + } + } + + return -1; } - return -1; -} + function callbacksFor(object) { + var callbacks = object._promiseCallbacks; -function callbacksFor(object) { - var callbacks = object._promiseCallbacks; + if (!callbacks) { + callbacks = object._promiseCallbacks = {}; + } - if (!callbacks) { - callbacks = object._promiseCallbacks = {}; + return callbacks; } - return callbacks; -} - -/** - @class RSVP.EventTarget -*/ -var EventTarget = { - /** - `RSVP.EventTarget.mixin` extends an object with EventTarget methods. For - Example: + @class RSVP.EventTarget + */ + var EventTarget = { - ```javascript - var object = {}; + /** + `RSVP.EventTarget.mixin` extends an object with EventTarget methods. For + Example: + ```javascript + let object = {}; + RSVP.EventTarget.mixin(object); + object.on('finished', function(event) { + // handle event + }); + object.trigger('finished', { detail: value }); + ``` + `EventTarget.mixin` also works with prototypes: + ```javascript + let Person = function() {}; + RSVP.EventTarget.mixin(Person.prototype); + let yehuda = new Person(); + let 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; + }, - RSVP.EventTarget.mixin(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) { + if (typeof callback !== 'function') { + throw new TypeError('Callback must be a function'); + } - object.on('finished', function(event) { - // handle event - }); + var allCallbacks = callbacksFor(this), + callbacks = undefined; - object.trigger('finished', { detail: value }); - ``` + callbacks = allCallbacks[eventName]; - `EventTarget.mixin` also works with prototypes: + if (!callbacks) { + callbacks = allCallbacks[eventName] = []; + } - ```javascript - var Person = function() {}; - RSVP.EventTarget.mixin(Person.prototype); + if (indexOf(callbacks, callback) === -1) { + callbacks.push(callback); + } + }, - var yehuda = new Person(); - var tom = new Person(); + /** + 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 + let callback1 = function(){}; + let 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 = callbacksFor(this), + callbacks = undefined, + index = undefined; - yehuda.on('poke', function(event) { - console.log('Yehuda says OW'); - }); + if (!callback) { + allCallbacks[eventName] = []; + return; + } - tom.on('poke', function(event) { - console.log('Tom says OW'); - }); + callbacks = allCallbacks[eventName]; - yehuda.trigger('poke'); - tom.trigger('poke'); - ``` + index = indexOf(callbacks, callback); - @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; - }, + if (index !== -1) { + callbacks.splice(index, 1); + } + }, - /** - Registers a callback to be executed when `eventName` is triggered + /** + 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 {*} options optional value to be passed to any event handlers for + the given `eventName` + */ + trigger: function (eventName, options, label) { + var allCallbacks = callbacksFor(this), + callbacks = undefined, + callback = undefined; - ```javascript - object.on('event', function(eventInfo){ - // handle the event - }); + 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]; - 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) { - if (typeof callback !== 'function') { - throw new TypeError('Callback must be a function'); + callback(options, label); + } + } } + }; - var allCallbacks = callbacksFor(this), callbacks; + var config = { + instrument: false + }; - callbacks = allCallbacks[eventName]; + EventTarget['mixin'](config); - if (!callbacks) { - callbacks = allCallbacks[eventName] = []; + function 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);` + config['on']('error', value); + return; } - if (indexOf(callbacks, callback) === -1) { - callbacks.push(callback); + if (arguments.length === 2) { + config[name] = value; + } else { + return config[name]; } - }, + } - /** - You can use `off` to stop firing a particular callback for an event: + function objectOrFunction(x) { + return typeof x === 'function' || typeof x === 'object' && x !== null; + } - ```javascript - function doStuff() { // do stuff! } - object.on('stuff', doStuff); + function isFunction(x) { + return typeof x === 'function'; + } - object.trigger('stuff'); // doStuff will be called + function isMaybeThenable(x) { + return typeof x === 'object' && x !== null; + } - // Unregister ONLY the doStuff callback - object.off('stuff', doStuff); - object.trigger('stuff'); // doStuff will NOT be called - ``` + var _isArray = undefined; + if (!Array.isArray) { + _isArray = function (x) { + return Object.prototype.toString.call(x) === '[object Array]'; + }; + } else { + _isArray = Array.isArray; + } - 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: + var isArray = _isArray; - ```javascript - var callback1 = function(){}; - var callback2 = function(){}; + // Date.now is not available in browsers < IE9 + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now#Compatibility + var now = Date.now || function () { + return new Date().getTime(); + }; - object.on('stuff', callback1); - object.on('stuff', callback2); + function F() {} - object.trigger('stuff'); // callback1 and callback2 will be executed. + var 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'); + } + F.prototype = o; + return new F(); + }; - object.off('stuff'); - object.trigger('stuff'); // callback1 and callback2 will not be executed! - ``` + var queue = []; - @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 = callbacksFor(this), callbacks, index; + function scheduleFlush() { + setTimeout(function () { + for (var i = 0; i < queue.length; i++) { + var entry = queue[i]; - if (!callback) { - allCallbacks[eventName] = []; - return; - } + var payload = entry.payload; - callbacks = allCallbacks[eventName]; + payload.guid = payload.key + payload.id; + payload.childGuid = payload.key + payload.childId; + if (payload.error) { + payload.stack = payload.error.stack; + } - index = indexOf(callbacks, callback); + config['trigger'](entry.name, entry.payload); + } + queue.length = 0; + }, 50); + } - if (index !== -1) { callbacks.splice(index, 1); } - }, + function instrument(eventName, promise, child) { + if (1 === queue.push({ + name: eventName, + payload: { + key: promise._guidKey, + id: promise._id, + eventName: eventName, + detail: promise._result, + childId: child && child._id, + label: promise._label, + timeStamp: now(), + error: config["instrument-with-stack"] ? new Error(promise._label) : null + } })) { + scheduleFlush(); + } + } /** - Use `trigger` to fire custom events. For example: - + `RSVP.Promise.resolve` returns a promise that will become resolved with the + passed `value`. It is shorthand for the following: + ```javascript - object.on('foo', function(){ - console.log('foo event happened!'); + let promise = new RSVP.Promise(function(resolve, reject){ + resolve(1); }); - object.trigger('foo'); - // 'foo event happened!' logged to the console + + promise.then(function(value){ + // value === 1 + }); ``` - - 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: - + + Instead of writing the above, your code now simply becomes the following: + ```javascript - object.on('foo', function(value){ - console.log(value.name); + let promise = RSVP.Promise.resolve(1); + + promise.then(function(value){ + // value === 1 }); - - 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 {*} options optional value to be passed to any event handlers for - the given `eventName` + + @method resolve + @static + @param {*} object value that the returned promise will be resolved with + @param {String} label optional string for identifying the returned promise. + Useful for tooling. + @return {Promise} a promise that will become fulfilled with the given + `value` */ - 'trigger': function(eventName, options, label) { - var allCallbacks = callbacksFor(this), callbacks, callback; + function resolve$1(object, label) { + /*jshint validthis:true */ + var Constructor = this; - 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, label); - } + if (object && typeof object === 'object' && object.constructor === Constructor) { + return object; } - } -}; -var config = { - instrument: false -}; - -EventTarget['mixin'](config); - -function 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);` - config['on']('error', value); - return; + var promise = new Constructor(noop, label); + resolve(promise, object); + return promise; } - if (arguments.length === 2) { - config[name] = value; - } else { - return config[name]; + function withOwnPromise() { + return new TypeError('A promises callback cannot return that same promise.'); } -} -function objectOrFunction(x) { - return typeof x === 'function' || (typeof x === 'object' && x !== null); -} + function noop() {} -function isFunction(x) { - return typeof x === 'function'; -} + var PENDING = void 0; + var FULFILLED = 1; + var REJECTED = 2; -function isMaybeThenable(x) { - return typeof x === 'object' && x !== null; -} + var GET_THEN_ERROR = new ErrorObject(); -var _isArray; -if (!Array.isArray) { - _isArray = function (x) { - return Object.prototype.toString.call(x) === '[object Array]'; - }; -} else { - _isArray = Array.isArray; -} - -var isArray = _isArray; - -// Date.now is not available in browsers < IE9 -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now#Compatibility -var now = Date.now || function() { return new Date().getTime(); }; - -function F() { } - -var o_create = (Object.create || function (o) { - if (arguments.length > 1) { - throw new Error('Second argument not supported'); + function getThen(promise) { + try { + return promise.then; + } catch (error) { + GET_THEN_ERROR.error = error; + return GET_THEN_ERROR; + } } - if (typeof o !== 'object') { - throw new TypeError('Argument must be an object'); - } - F.prototype = o; - return new F(); -}); -var queue = []; - -function scheduleFlush() { - setTimeout(function() { - var entry; - for (var i = 0; i < queue.length; i++) { - entry = queue[i]; - - var payload = entry.payload; - - payload.guid = payload.key + payload.id; - payload.childGuid = payload.key + payload.childId; - if (payload.error) { - payload.stack = payload.error.stack; - } - - config['trigger'](entry.name, entry.payload); + function tryThen(then, value, fulfillmentHandler, rejectionHandler) { + try { + then.call(value, fulfillmentHandler, rejectionHandler); + } catch (e) { + return e; } - queue.length = 0; - }, 50); -} - -function instrument(eventName, promise, child) { - if (1 === queue.push({ - name: eventName, - payload: { - key: promise._guidKey, - id: promise._id, - eventName: eventName, - detail: promise._result, - childId: child && child._id, - label: promise._label, - timeStamp: now(), - error: config["instrument-with-stack"] ? new Error(promise._label) : null - }})) { - scheduleFlush(); - } } -/** - `RSVP.Promise.resolve` returns a promise that will become resolved with the - passed `value`. It is shorthand for the following: + function handleForeignThenable(promise, thenable, then) { + config.async(function (promise) { + var sealed = false; + var error = tryThen(then, thenable, function (value) { + if (sealed) { + return; + } + sealed = true; + if (thenable !== value) { + resolve(promise, value, undefined); + } else { + fulfill(promise, value); + } + }, function (reason) { + if (sealed) { + return; + } + sealed = true; - ```javascript - var promise = new RSVP.Promise(function(resolve, reject){ - resolve(1); - }); + reject(promise, reason); + }, 'Settle: ' + (promise._label || ' unknown promise')); - promise.then(function(value){ - // value === 1 - }); - ``` - - Instead of writing the above, your code now simply becomes the following: - - ```javascript - var promise = RSVP.Promise.resolve(1); - - promise.then(function(value){ - // value === 1 - }); - ``` - - @method resolve - @static - @param {*} object value that the returned promise will be resolved with - @param {String} label optional string for identifying the returned promise. - Useful for tooling. - @return {Promise} a promise that will become fulfilled with the given - `value` -*/ -function resolve$1(object, label) { - /*jshint validthis:true */ - var Constructor = this; - - if (object && typeof object === 'object' && object.constructor === Constructor) { - return object; + if (!sealed && error) { + sealed = true; + reject(promise, error); + } + }, promise); } - var promise = new Constructor(noop, label); - resolve(promise, object); - return promise; -} - -function withOwnPromise() { - return new TypeError('A promises callback cannot return that same promise.'); -} - -function noop() {} - -var PENDING = void 0; -var FULFILLED = 1; -var REJECTED = 2; - -var GET_THEN_ERROR = new ErrorObject(); - -function getThen(promise) { - try { - return promise.then; - } catch(error) { - GET_THEN_ERROR.error = error; - return GET_THEN_ERROR; + function handleOwnThenable(promise, thenable) { + if (thenable._state === FULFILLED) { + fulfill(promise, thenable._result); + } else if (thenable._state === REJECTED) { + thenable._onError = null; + reject(promise, thenable._result); + } else { + subscribe(thenable, undefined, function (value) { + if (thenable !== value) { + resolve(promise, value, undefined); + } else { + fulfill(promise, value); + } + }, function (reason) { + return reject(promise, reason); + }); + } } -} -function tryThen(then, value, fulfillmentHandler, rejectionHandler) { - try { - then.call(value, fulfillmentHandler, rejectionHandler); - } catch(e) { - return e; - } -} - -function handleForeignThenable(promise, thenable, then) { - config.async(function(promise) { - var sealed = false; - var error = tryThen(then, thenable, function(value) { - if (sealed) { return; } - sealed = true; - if (thenable !== value) { - resolve(promise, value, undefined); + function handleMaybeThenable(promise, maybeThenable, then$$) { + if (maybeThenable.constructor === promise.constructor && then$$ === then && promise.constructor.resolve === resolve$1) { + handleOwnThenable(promise, maybeThenable); + } else { + if (then$$ === GET_THEN_ERROR) { + reject(promise, GET_THEN_ERROR.error); + } else if (then$$ === undefined) { + fulfill(promise, maybeThenable); + } else if (isFunction(then$$)) { + handleForeignThenable(promise, maybeThenable, then$$); } else { - fulfill(promise, value); + fulfill(promise, maybeThenable); } - }, function(reason) { - if (sealed) { return; } - sealed = true; - - reject(promise, reason); - }, 'Settle: ' + (promise._label || ' unknown promise')); - - if (!sealed && error) { - sealed = true; - reject(promise, error); } - }, promise); -} - -function handleOwnThenable(promise, thenable) { - if (thenable._state === FULFILLED) { - fulfill(promise, thenable._result); - } else if (thenable._state === REJECTED) { - thenable._onError = null; - reject(promise, thenable._result); - } else { - subscribe(thenable, undefined, function(value) { - if (thenable !== value) { - resolve(promise, value, undefined); - } else { - fulfill(promise, value); - } - }, function(reason) { - reject(promise, reason); - }); } -} -function handleMaybeThenable(promise, maybeThenable, then$$) { - if (maybeThenable.constructor === promise.constructor && - then$$ === then && - constructor.resolve === resolve$1) { - handleOwnThenable(promise, maybeThenable); - } else { - if (then$$ === GET_THEN_ERROR) { - reject(promise, GET_THEN_ERROR.error); - } else if (then$$ === undefined) { - fulfill(promise, maybeThenable); - } else if (isFunction(then$$)) { - handleForeignThenable(promise, maybeThenable, then$$); + function resolve(promise, value) { + if (promise === value) { + fulfill(promise, value); + } else if (objectOrFunction(value)) { + handleMaybeThenable(promise, value, getThen(value)); } else { - fulfill(promise, maybeThenable); + fulfill(promise, value); } } -} -function resolve(promise, value) { - if (promise === value) { - fulfill(promise, value); - } else if (objectOrFunction(value)) { - handleMaybeThenable(promise, value, getThen(value)); - } else { - fulfill(promise, value); - } -} + function publishRejection(promise) { + if (promise._onError) { + promise._onError(promise._result); + } -function publishRejection(promise) { - if (promise._onError) { - promise._onError(promise._result); + publish(promise); } - publish(promise); -} + function fulfill(promise, value) { + if (promise._state !== PENDING) { + return; + } -function fulfill(promise, value) { - if (promise._state !== PENDING) { return; } + promise._result = value; + promise._state = FULFILLED; - promise._result = value; - promise._state = FULFILLED; - - if (promise._subscribers.length === 0) { - if (config.instrument) { - instrument('fulfilled', promise); + if (promise._subscribers.length === 0) { + if (config.instrument) { + instrument('fulfilled', promise); + } + } else { + config.async(publish, promise); } - } else { - config.async(publish, promise); } -} -function reject(promise, reason) { - if (promise._state !== PENDING) { return; } - promise._state = REJECTED; - promise._result = reason; - config.async(publishRejection, promise); -} - -function subscribe(parent, child, onFulfillment, onRejection) { - var subscribers = parent._subscribers; - var length = subscribers.length; - - parent._onError = null; - - subscribers[length] = child; - subscribers[length + FULFILLED] = onFulfillment; - subscribers[length + REJECTED] = onRejection; - - if (length === 0 && parent._state) { - config.async(publish, parent); + function reject(promise, reason) { + if (promise._state !== PENDING) { + return; + } + promise._state = REJECTED; + promise._result = reason; + config.async(publishRejection, promise); } -} -function publish(promise) { - var subscribers = promise._subscribers; - var settled = promise._state; + function subscribe(parent, child, onFulfillment, onRejection) { + var subscribers = parent._subscribers; + var length = subscribers.length; - if (config.instrument) { - instrument(settled === FULFILLED ? 'fulfilled' : 'rejected', promise); - } + parent._onError = null; - if (subscribers.length === 0) { return; } + subscribers[length] = child; + subscribers[length + FULFILLED] = onFulfillment; + subscribers[length + REJECTED] = onRejection; - var child, callback, detail = promise._result; - - for (var i = 0; i < subscribers.length; i += 3) { - child = subscribers[i]; - callback = subscribers[i + settled]; - - if (child) { - invokeCallback(settled, child, callback, detail); - } else { - callback(detail); + if (length === 0 && parent._state) { + config.async(publish, parent); } } - promise._subscribers.length = 0; -} + function publish(promise) { + var subscribers = promise._subscribers; + var settled = promise._state; -function ErrorObject() { - this.error = null; -} - -var TRY_CATCH_ERROR = new ErrorObject(); - -function tryCatch(callback, detail) { - try { - return callback(detail); - } catch(e) { - TRY_CATCH_ERROR.error = e; - return TRY_CATCH_ERROR; - } -} - -function invokeCallback(settled, promise, callback, detail) { - var hasCallback = isFunction(callback), - value, error, succeeded, failed; - - if (hasCallback) { - value = tryCatch(callback, detail); - - if (value === TRY_CATCH_ERROR) { - failed = true; - error = value.error; - value = null; - } else { - succeeded = true; + if (config.instrument) { + instrument(settled === FULFILLED ? 'fulfilled' : 'rejected', promise); } - if (promise === value) { - reject(promise, withOwnPromise()); + if (subscribers.length === 0) { return; } - } else { - value = detail; - succeeded = true; - } + var child = undefined, + callback = undefined, + detail = promise._result; - if (promise._state !== PENDING) { - // noop - } else if (hasCallback && succeeded) { - resolve(promise, value); - } else if (failed) { - reject(promise, error); - } else if (settled === FULFILLED) { - fulfill(promise, value); - } else if (settled === REJECTED) { - reject(promise, value); - } -} + for (var i = 0; i < subscribers.length; i += 3) { + child = subscribers[i]; + callback = subscribers[i + settled]; -function initializePromise(promise, resolver) { - var resolved = false; - try { - resolver(function resolvePromise(value){ - if (resolved) { return; } - resolved = true; - resolve(promise, value); - }, function rejectPromise(reason) { - if (resolved) { return; } - resolved = true; - reject(promise, reason); - }); - } catch(e) { - reject(promise, e); - } -} + if (child) { + invokeCallback(settled, child, callback, detail); + } else { + callback(detail); + } + } -function then(onFulfillment, onRejection, label) { - var parent = this; - var state = parent._state; - - if (state === FULFILLED && !onFulfillment || state === REJECTED && !onRejection) { - config.instrument && instrument('chained', parent, parent); - return parent; + promise._subscribers.length = 0; } - parent._onError = null; - - var child = new parent.constructor(noop, label); - var result = parent._result; - - config.instrument && instrument('chained', parent, child); - - if (state) { - var callback = arguments[state - 1]; - config.async(function(){ - invokeCallback(state, child, callback, result); - }); - } else { - subscribe(parent, child, onFulfillment, onRejection); + function ErrorObject() { + this.error = null; } - return child; -} + var TRY_CATCH_ERROR = new ErrorObject(); -function makeSettledResult(state, position, value) { - if (state === FULFILLED) { - return { - state: 'fulfilled', - value: value - }; - } else { - return { - state: 'rejected', - reason: value - }; + function tryCatch(callback, detail) { + try { + return callback(detail); + } catch (e) { + TRY_CATCH_ERROR.error = e; + return TRY_CATCH_ERROR; + } } -} -function Enumerator(Constructor, input, abortOnReject, label) { - this._instanceConstructor = Constructor; - this.promise = new Constructor(noop, label); - this._abortOnReject = abortOnReject; + function invokeCallback(settled, promise, callback, detail) { + var hasCallback = isFunction(callback), + value = undefined, + error = undefined, + succeeded = undefined, + failed = undefined; - if (this._validateInput(input)) { - this._input = input; - this.length = input.length; - this._remaining = input.length; + if (hasCallback) { + value = tryCatch(callback, detail); - this._init(); + if (value === TRY_CATCH_ERROR) { + failed = true; + error = value.error; + value = null; + } else { + succeeded = true; + } - if (this.length === 0) { - fulfill(this.promise, this._result); + if (promise === value) { + reject(promise, withOwnPromise()); + return; + } } else { - this.length = this.length || 0; - this._enumerate(); - if (this._remaining === 0) { - fulfill(this.promise, this._result); + value = detail; + succeeded = true; + } + + if (promise._state !== PENDING) { + // noop + } else if (hasCallback && succeeded) { + resolve(promise, value); + } else if (failed) { + reject(promise, error); + } else if (settled === FULFILLED) { + fulfill(promise, value); + } else if (settled === REJECTED) { + reject(promise, value); } + } + + function initializePromise(promise, resolver) { + var resolved = false; + try { + resolver(function (value) { + if (resolved) { + return; + } + resolved = true; + resolve(promise, value); + }, function (reason) { + if (resolved) { + return; + } + resolved = true; + reject(promise, reason); + }); + } catch (e) { + reject(promise, e); } - } else { - reject(this.promise, this._validationError()); } -} -Enumerator.prototype._validateInput = function(input) { - return isArray(input); -}; + function then(onFulfillment, onRejection, label) { + var _arguments = arguments; -Enumerator.prototype._validationError = function() { - return new Error('Array Methods must be provided an Array'); -}; + var parent = this; + var state = parent._state; -Enumerator.prototype._init = function() { - this._result = new Array(this.length); -}; + if (state === FULFILLED && !onFulfillment || state === REJECTED && !onRejection) { + config.instrument && instrument('chained', parent, parent); + return parent; + } -Enumerator.prototype._enumerate = function() { - var length = this.length; - var promise = this.promise; - var input = this._input; + parent._onError = null; - for (var i = 0; promise._state === PENDING && i < length; i++) { - this._eachEntry(input[i], i); - } -}; + var child = new parent.constructor(noop, label); + var result = parent._result; -Enumerator.prototype._settleMaybeThenable = function(entry, i) { - var c = this._instanceConstructor; - var resolve = c.resolve; + config.instrument && instrument('chained', parent, child); - if (resolve === resolve$1) { - var then$$ = getThen(entry); - - if (then$$ === then && - entry._state !== PENDING) { - entry._onError = null; - this._settledAt(entry._state, i, entry._result); - } else if (typeof then$$ !== 'function') { - this._remaining--; - this._result[i] = this._makeResult(FULFILLED, i, entry); - } else if (c === Promise) { - var promise = new c(noop); - handleMaybeThenable(promise, entry, then$$); - this._willSettleAt(promise, i); + if (state) { + (function () { + var callback = _arguments[state - 1]; + config.async(function () { + return invokeCallback(state, child, callback, result); + }); + })(); } else { - this._willSettleAt(new c(function(resolve) { resolve(entry); }), i); + subscribe(parent, child, onFulfillment, onRejection); } - } else { - this._willSettleAt(resolve(entry), i); - } -}; -Enumerator.prototype._eachEntry = function(entry, i) { - if (isMaybeThenable(entry)) { - this._settleMaybeThenable(entry, i); - } else { - this._remaining--; - this._result[i] = this._makeResult(FULFILLED, i, entry); + return child; } -}; -Enumerator.prototype._settledAt = function(state, i, value) { - var promise = this.promise; - - if (promise._state === PENDING) { - this._remaining--; - - if (this._abortOnReject && state === REJECTED) { - reject(promise, value); + function makeSettledResult(state, position, value) { + if (state === FULFILLED) { + return { + state: 'fulfilled', + value: value + }; } else { - this._result[i] = this._makeResult(state, i, value); + return { + state: 'rejected', + reason: value + }; } } - if (this._remaining === 0) { - fulfill(promise, this._result); - } -}; + function Enumerator(Constructor, input, abortOnReject, label) { + this._instanceConstructor = Constructor; + this.promise = new Constructor(noop, label); + this._abortOnReject = abortOnReject; -Enumerator.prototype._makeResult = function(state, i, value) { - return value; -}; + if (this._validateInput(input)) { + this._input = input; + this.length = input.length; + this._remaining = input.length; -Enumerator.prototype._willSettleAt = function(promise, i) { - var enumerator = this; + this._init(); - subscribe(promise, undefined, function(value) { - enumerator._settledAt(FULFILLED, i, value); - }, function(reason) { - enumerator._settledAt(REJECTED, i, reason); - }); -}; + if (this.length === 0) { + fulfill(this.promise, this._result); + } else { + this.length = this.length || 0; + this._enumerate(); + if (this._remaining === 0) { + fulfill(this.promise, this._result); + } + } + } else { + reject(this.promise, this._validationError()); + } + } -/** - `RSVP.Promise.all` accepts an array of promises, and returns a new promise which - is fulfilled with an array of fulfillment values for the passed promises, or - rejected with the reason of the first passed promise to be rejected. It casts all - elements of the passed iterable to promises as it runs this algorithm. + Enumerator.prototype._validateInput = function (input) { + return isArray(input); + }; - Example: + Enumerator.prototype._validationError = function () { + return new Error('Array Methods must be provided an Array'); + }; - ```javascript - var promise1 = RSVP.resolve(1); - var promise2 = RSVP.resolve(2); - var promise3 = RSVP.resolve(3); - var promises = [ promise1, promise2, promise3 ]; + Enumerator.prototype._init = function () { + this._result = new Array(this.length); + }; - RSVP.Promise.all(promises).then(function(array){ - // The array here would be [ 1, 2, 3 ]; - }); - ``` + Enumerator.prototype._enumerate = function () { + var length = this.length; + var promise = this.promise; + var input = this._input; - If any of the `promises` given to `RSVP.all` are rejected, the first promise - that is rejected will be given as an argument to the returned promises's - rejection handler. For example: + for (var i = 0; promise._state === PENDING && i < length; i++) { + this._eachEntry(input[i], i); + } + }; - Example: + Enumerator.prototype._settleMaybeThenable = function (entry, i) { + var c = this._instanceConstructor; + var resolve = c.resolve; - ```javascript - var promise1 = RSVP.resolve(1); - var promise2 = RSVP.reject(new Error("2")); - var promise3 = RSVP.reject(new Error("3")); - var promises = [ promise1, promise2, promise3 ]; + if (resolve === resolve$1) { + var then$$ = getThen(entry); - RSVP.Promise.all(promises).then(function(array){ - // Code here never runs because there are rejected promises! - }, function(error) { - // error.message === "2" - }); - ``` + if (then$$ === then && entry._state !== PENDING) { + entry._onError = null; + this._settledAt(entry._state, i, entry._result); + } else if (typeof then$$ !== 'function') { + this._remaining--; + this._result[i] = this._makeResult(FULFILLED, i, entry); + } else if (c === Promise) { + var promise = new c(noop); + handleMaybeThenable(promise, entry, then$$); + this._willSettleAt(promise, i); + } else { + this._willSettleAt(new c(function (resolve) { + return resolve(entry); + }), i); + } + } else { + this._willSettleAt(resolve(entry), i); + } + }; - @method all - @static - @param {Array} entries array of promises - @param {String} label optional string for labeling the promise. - Useful for tooling. - @return {Promise} promise that is fulfilled when all `promises` have been - fulfilled, or rejected if any of them become rejected. - @static -*/ -function all(entries, label) { - return new Enumerator(this, entries, true /* abort on reject */, label).promise; -} + Enumerator.prototype._eachEntry = function (entry, i) { + if (isMaybeThenable(entry)) { + this._settleMaybeThenable(entry, i); + } else { + this._remaining--; + this._result[i] = this._makeResult(FULFILLED, i, entry); + } + }; -/** - `RSVP.Promise.race` returns a new promise which is settled in the same way as the - first passed promise to settle. + Enumerator.prototype._settledAt = function (state, i, value) { + var promise = this.promise; - Example: + if (promise._state === PENDING) { + this._remaining--; - ```javascript - var promise1 = new RSVP.Promise(function(resolve, reject){ - setTimeout(function(){ - resolve('promise 1'); - }, 200); - }); + if (this._abortOnReject && state === REJECTED) { + reject(promise, value); + } else { + this._result[i] = this._makeResult(state, i, value); + } + } - var promise2 = new RSVP.Promise(function(resolve, reject){ - setTimeout(function(){ - resolve('promise 2'); - }, 100); - }); + if (this._remaining === 0) { + fulfill(promise, this._result); + } + }; - RSVP.Promise.race([promise1, promise2]).then(function(result){ - // result === 'promise 2' because it was resolved before promise1 - // was resolved. - }); - ``` + Enumerator.prototype._makeResult = function (state, i, value) { + return value; + }; - `RSVP.Promise.race` is deterministic in that only the state of the first - settled promise matters. For example, even if other promises given to the - `promises` array argument are resolved, but the first settled promise has - become rejected before the other promises became fulfilled, the returned - promise will become rejected: + Enumerator.prototype._willSettleAt = function (promise, i) { + var enumerator = this; - ```javascript - var promise1 = new RSVP.Promise(function(resolve, reject){ - setTimeout(function(){ - resolve('promise 1'); - }, 200); - }); + subscribe(promise, undefined, function (value) { + return enumerator._settledAt(FULFILLED, i, value); + }, function (reason) { + return enumerator._settledAt(REJECTED, i, reason); + }); + }; - var promise2 = new RSVP.Promise(function(resolve, reject){ - setTimeout(function(){ - reject(new Error('promise 2')); - }, 100); - }); + /** + `RSVP.Promise.all` accepts an array of promises, and returns a new promise which + is fulfilled with an array of fulfillment values for the passed promises, or + rejected with the reason of the first passed promise to be rejected. It casts all + elements of the passed iterable to promises as it runs this algorithm. + + Example: + + ```javascript + let promise1 = RSVP.resolve(1); + let promise2 = RSVP.resolve(2); + let promise3 = RSVP.resolve(3); + let promises = [ promise1, promise2, promise3 ]; + + RSVP.Promise.all(promises).then(function(array){ + // The array here would be [ 1, 2, 3 ]; + }); + ``` + + If any of the `promises` given to `RSVP.all` are rejected, the first promise + that is rejected will be given as an argument to the returned promises's + rejection handler. For example: + + Example: + + ```javascript + let promise1 = RSVP.resolve(1); + let promise2 = RSVP.reject(new Error("2")); + let promise3 = RSVP.reject(new Error("3")); + let promises = [ promise1, promise2, promise3 ]; + + RSVP.Promise.all(promises).then(function(array){ + // Code here never runs because there are rejected promises! + }, function(error) { + // error.message === "2" + }); + ``` + + @method all + @static + @param {Array} entries array of promises + @param {String} label optional string for labeling the promise. + Useful for tooling. + @return {Promise} promise that is fulfilled when all `promises` have been + fulfilled, or rejected if any of them become rejected. + @static + */ + function all(entries, label) { + return new Enumerator(this, entries, true, /* abort on reject */label).promise; + } - RSVP.Promise.race([promise1, promise2]).then(function(result){ - // Code here never runs - }, function(reason){ - // reason.message === 'promise 2' because promise 2 became rejected before - // promise 1 became fulfilled - }); - ``` + /** + `RSVP.Promise.race` returns a new promise which is settled in the same way as the + first passed promise to settle. + + Example: + + ```javascript + let promise1 = new RSVP.Promise(function(resolve, reject){ + setTimeout(function(){ + resolve('promise 1'); + }, 200); + }); + + let promise2 = new RSVP.Promise(function(resolve, reject){ + setTimeout(function(){ + resolve('promise 2'); + }, 100); + }); + + RSVP.Promise.race([promise1, promise2]).then(function(result){ + // result === 'promise 2' because it was resolved before promise1 + // was resolved. + }); + ``` + + `RSVP.Promise.race` is deterministic in that only the state of the first + settled promise matters. For example, even if other promises given to the + `promises` array argument are resolved, but the first settled promise has + become rejected before the other promises became fulfilled, the returned + promise will become rejected: + + ```javascript + let promise1 = new RSVP.Promise(function(resolve, reject){ + setTimeout(function(){ + resolve('promise 1'); + }, 200); + }); + + let promise2 = new RSVP.Promise(function(resolve, reject){ + setTimeout(function(){ + reject(new Error('promise 2')); + }, 100); + }); + + RSVP.Promise.race([promise1, promise2]).then(function(result){ + // Code here never runs + }, function(reason){ + // reason.message === 'promise 2' because promise 2 became rejected before + // promise 1 became fulfilled + }); + ``` + + An example real-world use case is implementing timeouts: + + ```javascript + RSVP.Promise.race([ajax('foo.json'), timeout(5000)]) + ``` + + @method race + @static + @param {Array} entries array of promises to observe + @param {String} label optional string for describing the promise returned. + Useful for tooling. + @return {Promise} a promise which settles in the same way as the first passed + promise to settle. + */ + function race(entries, label) { + /*jshint validthis:true */ + var Constructor = this; - An example real-world use case is implementing timeouts: + var promise = new Constructor(noop, label); - ```javascript - RSVP.Promise.race([ajax('foo.json'), timeout(5000)]) - ``` + if (!isArray(entries)) { + reject(promise, new TypeError('You must pass an array to race.')); + return promise; + } - @method race - @static - @param {Array} entries array of promises to observe - @param {String} label optional string for describing the promise returned. - Useful for tooling. - @return {Promise} a promise which settles in the same way as the first passed - promise to settle. -*/ -function race(entries, label) { - /*jshint validthis:true */ - var Constructor = this; + for (var i = 0; promise._state === PENDING && i < entries.length; i++) { + subscribe(Constructor.resolve(entries[i]), undefined, function (value) { + return resolve(promise, value); + }, function (reason) { + return reject(promise, reason); + }); + } - var promise = new Constructor(noop, label); - - if (!isArray(entries)) { - reject(promise, new TypeError('You must pass an array to race.')); return promise; } - var length = entries.length; - - function onFulfillment(value) { - resolve(promise, value); - } - - function onRejection(reason) { + /** + `RSVP.Promise.reject` returns a promise rejected with the passed `reason`. + It is shorthand for the following: + + ```javascript + let promise = new RSVP.Promise(function(resolve, reject){ + reject(new Error('WHOOPS')); + }); + + promise.then(function(value){ + // Code here doesn't run because the promise is rejected! + }, function(reason){ + // reason.message === 'WHOOPS' + }); + ``` + + Instead of writing the above, your code now simply becomes the following: + + ```javascript + let promise = RSVP.Promise.reject(new Error('WHOOPS')); + + promise.then(function(value){ + // Code here doesn't run because the promise is rejected! + }, function(reason){ + // reason.message === 'WHOOPS' + }); + ``` + + @method reject + @static + @param {*} reason value that the returned promise will be rejected with. + @param {String} label optional string for identifying the returned promise. + Useful for tooling. + @return {Promise} a promise rejected with the given `reason`. + */ + function reject$1(reason, label) { + /*jshint validthis:true */ + var Constructor = this; + var promise = new Constructor(noop, label); reject(promise, reason); + return promise; } - for (var i = 0; promise._state === PENDING && i < length; i++) { - subscribe(Constructor.resolve(entries[i]), undefined, onFulfillment, onRejection); - } + var guidKey = 'rsvp_' + now() + '-'; + var counter = 0; - return promise; -} - -/** - `RSVP.Promise.reject` returns a promise rejected with the passed `reason`. - It is shorthand for the following: - - ```javascript - var promise = new RSVP.Promise(function(resolve, reject){ - reject(new Error('WHOOPS')); - }); - - promise.then(function(value){ - // Code here doesn't run because the promise is rejected! - }, function(reason){ - // reason.message === 'WHOOPS' - }); - ``` - - Instead of writing the above, your code now simply becomes the following: - - ```javascript - var promise = RSVP.Promise.reject(new Error('WHOOPS')); - - promise.then(function(value){ - // Code here doesn't run because the promise is rejected! - }, function(reason){ - // reason.message === 'WHOOPS' - }); - ``` - - @method reject - @static - @param {*} reason value that the returned promise will be rejected with. - @param {String} label optional string for identifying the returned promise. - Useful for tooling. - @return {Promise} a promise rejected with the given `reason`. -*/ -function reject$1(reason, label) { - /*jshint validthis:true */ - var Constructor = this; - var promise = new Constructor(noop, label); - reject(promise, reason); - return promise; -} - -var guidKey = 'rsvp_' + now() + '-'; -var counter = 0; - -function needsResolver() { - throw new TypeError('You must pass a resolver function as the first argument to the promise constructor'); -} - -function needsNew() { - throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function."); -} - -/** - 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 + ']')); - } - } - }; - }); + function needsResolver() { + throw new TypeError('You must pass a resolver function as the first argument to the promise constructor'); } - 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 Promise(resolver, label) { - this._id = counter++; - this._label = label; - this._state = undefined; - this._result = undefined; - this._subscribers = []; - - config.instrument && instrument('created', this); - - if (noop !== resolver) { - typeof resolver !== 'function' && needsResolver(); - this instanceof Promise ? initializePromise(this, resolver) : needsNew(); + function needsNew() { + throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function."); } -} -Promise.cast = resolve$1; // deprecated -Promise.all = all; -Promise.race = race; -Promise.resolve = resolve$1; -Promise.reject = reject$1; - -Promise.prototype = { - constructor: Promise, - - _guidKey: guidKey, - - _onError: function (reason) { - var promise = this; - config.after(function() { - if (promise._onError) { - config['trigger']('error', reason, promise._label); - } + /** + 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 + let promise = new Promise(function(resolve, reject) { + // on success + resolve(value); + + // on failure + reject(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.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){ + let 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 Promise(resolver, label) { + this._id = counter++; + this._label = label; + this._state = undefined; + this._result = undefined; + this._subscribers = []; - Promise Example; + config.instrument && instrument('created', this); - ```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 + if (noop !== resolver) { + typeof resolver !== 'function' && needsResolver(); + this instanceof Promise ? initializePromise(this, resolver) : needsNew(); + } } - ``` - Errback Example + Promise.cast = resolve$1; // deprecated + Promise.all = all; + Promise.race = race; + Promise.resolve = resolve$1; + Promise.reject = reject$1; - ```js + Promise.prototype = { + constructor: Promise, - function foundBooks(books) { + _guidKey: guidKey, - } + _onError: function (reason) { + var promise = this; + config.after(function () { + if (promise._onError) { + config['trigger']('error', reason, promise._label); + } + }); + }, - function failure(reason) { - - } - - findAuthor(function(author, err){ - if (err) { - failure(err); - // failure - } else { + /** + 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 + let result; + try { - findBoooksByAuthor(author, function(books, err) { - if (err) { + 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 + let 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); - } else { - try { - foundBooks(books); - } catch(reason) { - failure(reason); - } } - }); + // success + } + }); + ``` + + Promise Example; + + ```javascript + findAuthor(). + then(findBooksByAuthor). + then(function(books){ + // found books + }).catch(function(reason){ + // something went wrong + }); + ``` + + @method then + @param {Function} onFulfillment + @param {Function} onRejection + @param {String} label optional string for labeling the promise. + Useful for tooling. + @return {Promise} + */ + then: then, + + /** + `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(undefined, 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) { - failure(err); + return findOtherAuther(); + } finally { + // always runs + // doesn't affect the return value } - // success + ``` + + 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 promise = this; + var constructor = promise.constructor; + + return promise.then(function (value) { + return constructor.resolve(callback()).then(function () { + return value; + }); + }, function (reason) { + return constructor.resolve(callback()).then(function () { + throw reason; + }); + }, label); } - }); - ``` + }; - Promise Example; - - ```javascript - findAuthor(). - then(findBooksByAuthor). - then(function(books){ - // found books - }).catch(function(reason){ - // something went wrong - }); - ``` - - @method then - @param {Function} onFulfillment - @param {Function} onRejection - @param {String} label optional string for labeling the promise. - Useful for tooling. - @return {Promise} -*/ - then: then, - -/** - `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'); + function Result() { + this.value = undefined; } - // synchronous - try { - findAuthor(); - } catch(reason) { - // something went wrong - } + var ERROR = new Result(); + var GET_THEN_ERROR$1 = new Result(); - // 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(undefined, 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(); + function getThen$1(obj) { + try { + return obj.then; + } catch (error) { + ERROR.value = error; + return ERROR; } - return new Author(); } - try { - return findAuthor(); // succeed or fail - } catch(error) { - return findOtherAuther(); - } finally { - // always runs - // doesn't affect the return value + function tryApply(f, s, a) { + try { + f.apply(s, a); + } catch (error) { + ERROR.value = error; + return ERROR; + } } - ``` - Asynchronous example: + function makeObject(_, argumentNames) { + var obj = {}; + var length = _.length; + var args = new Array(length); - ```js - findAuthor().catch(function(reason){ - return findOtherAuther(); - }).finally(function(){ - // author was either found, or not - }); - ``` + for (var x = 0; x < length; x++) { + args[x] = _[x]; + } - @method finally - @param {Function} callback - @param {String} label optional string for labeling the promise. - Useful for tooling. - @return {Promise} -*/ - 'finally': function(callback, label) { - var promise = this; - var constructor = promise.constructor; + for (var i = 0; i < argumentNames.length; i++) { + var _name = argumentNames[i]; + obj[_name] = args[i + 1]; + } - return promise.then(function(value) { - return constructor.resolve(callback()).then(function() { - return value; - }); - }, function(reason) { - return constructor.resolve(callback()).then(function() { - return constructor.reject(reason); - }); - }, label); + return obj; } -}; -function Result() { - this.value = undefined; -} + function arrayResult(_) { + var length = _.length; + var args = new Array(length - 1); -var ERROR = new Result(); -var GET_THEN_ERROR$1 = new Result(); + for (var i = 1; i < length; i++) { + args[i - 1] = _[i]; + } -function getThen$1(obj) { - try { - return obj.then; - } catch(error) { - ERROR.value= error; - return ERROR; + return args; } -} - -function tryApply(f, s, a) { - try { - f.apply(s, a); - } catch(error) { - ERROR.value = error; - return ERROR; + function wrapThenable(then, promise) { + return { + then: function (onFulFillment, onRejection) { + return then.call(promise, onFulFillment, onRejection); + } + }; } -} -function 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 arrayResult(_) { - var length = _.length; - var args = new Array(length - 1); - - for (var i = 1; i < length; i++) { - args[i - 1] = _[i]; - } - - return args; -} - -function wrapThenable(then, promise) { - return { - then: function(onFulFillment, onRejection) { - return then.call(promise, onFulFillment, onRejection); - } - }; -} - -/** - `RSVP.denodeify` takes a 'node-style' function and returns a function that - will return an `RSVP.Promise`. You can use `denodeify` in Node.js or the - browser when you'd prefer to use promises over using callbacks. For example, - `denodeify` transforms the following: - - ```javascript - var fs = require('fs'); - - fs.readFile('myfile.txt', function(err, data){ - if (err) return handleError(err); - handleData(data); - }); - ``` - - into: - - ```javascript - var fs = require('fs'); - var readFile = RSVP.denodeify(fs.readFile); - - readFile('myfile.txt').then(handleData, handleError); - ``` - - If the node function has multiple success parameters, then `denodeify` - just returns the first one: - - ```javascript - var request = RSVP.denodeify(require('request')); - - request('http://example.com').then(function(res) { - // ... - }); - ``` - - However, if you need all success parameters, setting `denodeify`'s - second parameter to `true` causes it to return all success parameters - as an array: - - ```javascript - var request = RSVP.denodeify(require('request'), true); - - request('http://example.com').then(function(result) { - // result[0] -> res - // result[1] -> body - }); - ``` - - Or if you pass it an array with names it returns the parameters as a hash: - - ```javascript - var request = RSVP.denodeify(require('request'), ['res', 'body']); - - request('http://example.com').then(function(result) { - // result.res - // result.body - }); - ``` - - Sometimes you need to retain the `this`: - - ```javascript - var app = require('express')(); - var render = RSVP.denodeify(app.render.bind(app)); - ``` - - The denodified function inherits from the original function. It works in all - environments, except IE 10 and below. Consequently all properties of the original - function are available to you. However, any properties you change on the - denodeified function won't be changed on the original function. Example: - - ```javascript - var request = RSVP.denodeify(require('request')), - cookieJar = request.jar(); // <- Inheritance is used here - - request('http://example.com', {jar: cookieJar}).then(function(res) { - // cookieJar.cookies holds now the cookies returned by example.com - }); - ``` - - Using `denodeify` makes it easier to compose asynchronous operations instead - of using callbacks. For example, instead of: - - ```javascript - var fs = require('fs'); - - fs.readFile('myfile.txt', function(err, data){ - if (err) { ... } // Handle error - fs.writeFile('myfile2.txt', data, function(err){ + /** + `RSVP.denodeify` takes a 'node-style' function and returns a function that + will return an `RSVP.Promise`. You can use `denodeify` in Node.js or the + browser when you'd prefer to use promises over using callbacks. For example, + `denodeify` transforms the following: + + ```javascript + let fs = require('fs'); + + fs.readFile('myfile.txt', function(err, data){ + if (err) return handleError(err); + handleData(data); + }); + ``` + + into: + + ```javascript + let fs = require('fs'); + let readFile = RSVP.denodeify(fs.readFile); + + readFile('myfile.txt').then(handleData, handleError); + ``` + + If the node function has multiple success parameters, then `denodeify` + just returns the first one: + + ```javascript + let request = RSVP.denodeify(require('request')); + + request('http://example.com').then(function(res) { + // ... + }); + ``` + + However, if you need all success parameters, setting `denodeify`'s + second parameter to `true` causes it to return all success parameters + as an array: + + ```javascript + let request = RSVP.denodeify(require('request'), true); + + request('http://example.com').then(function(result) { + // result[0] -> res + // result[1] -> body + }); + ``` + + Or if you pass it an array with names it returns the parameters as a hash: + + ```javascript + let request = RSVP.denodeify(require('request'), ['res', 'body']); + + request('http://example.com').then(function(result) { + // result.res + // result.body + }); + ``` + + Sometimes you need to retain the `this`: + + ```javascript + let app = require('express')(); + let render = RSVP.denodeify(app.render.bind(app)); + ``` + + The denodified function inherits from the original function. It works in all + environments, except IE 10 and below. Consequently all properties of the original + function are available to you. However, any properties you change on the + denodeified function won't be changed on the original function. Example: + + ```javascript + let request = RSVP.denodeify(require('request')), + cookieJar = request.jar(); // <- Inheritance is used here + + request('http://example.com', {jar: cookieJar}).then(function(res) { + // cookieJar.cookies holds now the cookies returned by example.com + }); + ``` + + Using `denodeify` makes it easier to compose asynchronous operations instead + of using callbacks. For example, instead of: + + ```javascript + let fs = require('fs'); + + fs.readFile('myfile.txt', function(err, data){ if (err) { ... } // Handle error + fs.writeFile('myfile2.txt', data, function(err){ + if (err) { ... } // Handle error + console.log('done') + }); + }); + ``` + + you can chain the operations together using `then` from the returned promise: + + ```javascript + let fs = require('fs'); + let readFile = RSVP.denodeify(fs.readFile); + let writeFile = RSVP.denodeify(fs.writeFile); + + readFile('myfile.txt').then(function(data){ + return writeFile('myfile2.txt', data); + }).then(function(){ console.log('done') + }).catch(function(error){ + // Handle error }); - }); - ``` + ``` + + @method denodeify + @static + @for RSVP + @param {Function} nodeFunc a 'node-style' function that takes a callback as + its last argument. The callback expects an error to be passed as its first + argument (if an error occurred, otherwise null), and the value from the + operation as its second argument ('function(err, value){ }'). + @param {Boolean|Array} [options] An optional paramter that if set + to `true` causes the promise to fulfill with the callback's success arguments + as an array. This is useful if the node function has multiple success + paramters. If you set this paramter to an array with names, the promise will + fulfill with a hash with these names as keys and the success parameters as + values. + @return {Function} a function that wraps `nodeFunc` to return an + `RSVP.Promise` + @static + */ + function denodeify(nodeFunc, options) { + var fn = function () { + var self = this; + var l = arguments.length; + var args = new Array(l + 1); + var promiseInput = false; - you can chain the operations together using `then` from the returned promise: + for (var i = 0; i < l; ++i) { + var arg = arguments[i]; - ```javascript - var fs = require('fs'); - var readFile = RSVP.denodeify(fs.readFile); - var writeFile = RSVP.denodeify(fs.writeFile); - - readFile('myfile.txt').then(function(data){ - return writeFile('myfile2.txt', data); - }).then(function(){ - console.log('done') - }).catch(function(error){ - // Handle error - }); - ``` - - @method denodeify - @static - @for RSVP - @param {Function} nodeFunc a 'node-style' function that takes a callback as - its last argument. The callback expects an error to be passed as its first - argument (if an error occurred, otherwise null), and the value from the - operation as its second argument ('function(err, value){ }'). - @param {Boolean|Array} [options] An optional paramter that if set - to `true` causes the promise to fulfill with the callback's success arguments - as an array. This is useful if the node function has multiple success - paramters. If you set this paramter to an array with names, the promise will - fulfill with a hash with these names as keys and the success parameters as - values. - @return {Function} a function that wraps `nodeFunc` to return an - `RSVP.Promise` - @static -*/ -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 = needsPromiseInput(arg); - if (promiseInput === GET_THEN_ERROR$1) { - var p = new Promise(noop); - reject(p, GET_THEN_ERROR$1.value); - return p; - } else if (promiseInput && promiseInput !== true) { - arg = wrapThenable(promiseInput, arg); + if (!promiseInput) { + // TODO: clean this up + promiseInput = needsPromiseInput(arg); + if (promiseInput === GET_THEN_ERROR$1) { + var p = new Promise(noop); + reject(p, GET_THEN_ERROR$1.value); + return p; + } else if (promiseInput && promiseInput !== true) { + arg = wrapThenable(promiseInput, arg); + } } + args[i] = arg; } - args[i] = arg; - } - var promise = new Promise(noop); + var promise = new Promise(noop); - args[l] = function(err, val) { - if (err) - reject(promise, err); - else if (options === undefined) - resolve(promise, val); - else if (options === true) - resolve(promise, arrayResult(arguments)); - else if (isArray(options)) - resolve(promise, makeObject(arguments, options)); - else - resolve(promise, val); + args[l] = function (err, val) { + if (err) reject(promise, err);else if (options === undefined) resolve(promise, val);else if (options === true) resolve(promise, arrayResult(arguments));else if (isArray(options)) resolve(promise, makeObject(arguments, options));else resolve(promise, val); + }; + + if (promiseInput) { + return handlePromiseInput(promise, args, nodeFunc, self); + } else { + return handleValueInput(promise, args, nodeFunc, self); + } }; - if (promiseInput) { - return handlePromiseInput(promise, args, nodeFunc, self); - } else { - return handleValueInput(promise, args, nodeFunc, self); - } - }; + babelHelpers.defaults(fn, nodeFunc); - fn.__proto__ = nodeFunc; - - return fn; -} - -function handleValueInput(promise, args, nodeFunc, self) { - var result = tryApply(nodeFunc, self, args); - if (result === ERROR) { - reject(promise, result.value); + return fn; } - return promise; -} -function handlePromiseInput(promise, args, nodeFunc, self){ - return Promise.all(args).then(function(args){ + function handleValueInput(promise, args, nodeFunc, self) { var result = tryApply(nodeFunc, self, args); if (result === ERROR) { reject(promise, result.value); } return promise; - }); -} + } -function needsPromiseInput(arg) { - if (arg && typeof arg === 'object') { - if (arg.constructor === Promise) { - return true; + function handlePromiseInput(promise, args, nodeFunc, self) { + return Promise.all(args).then(function (args) { + var result = tryApply(nodeFunc, self, args); + if (result === ERROR) { + reject(promise, result.value); + } + return promise; + }); + } + + function needsPromiseInput(arg) { + if (arg && typeof arg === 'object') { + if (arg.constructor === Promise) { + return true; + } else { + return getThen$1(arg); + } } else { - return getThen$1(arg); + return false; } - } else { - return false; } -} -/** - This is a convenient alias for `RSVP.Promise.all`. - - @method all - @static - @for RSVP - @param {Array} array Array of promises. - @param {String} label An optional label. This is useful - for tooling. -*/ -function all$1(array, label) { - return Promise.all(array, label); -} - -function AllSettled(Constructor, entries, label) { - this._superConstructor(Constructor, entries, false /* don't abort on reject */, label); -} - -AllSettled.prototype = o_create(Enumerator.prototype); -AllSettled.prototype._superConstructor = Enumerator; -AllSettled.prototype._makeResult = makeSettledResult; -AllSettled.prototype._validationError = function() { - return new Error('allSettled must be called with an array'); -}; - -/** - `RSVP.allSettled` is similar to `RSVP.all`, but instead of implementing - a fail-fast method, it waits until all the promises have returned and - shows you all the results. This is useful if you want to handle multiple - promises' failure states together as a set. - - Returns a promise that is fulfilled when all the given promises have been - settled. The return promise is fulfilled with an array of the states of - the promises passed into the `promises` array argument. - - Each state object will either indicate fulfillment or rejection, and - provide the corresponding value or reason. The states will take one of - the following formats: - - ```javascript - { state: 'fulfilled', value: value } - or - { state: 'rejected', reason: reason } - ``` - - Example: - - ```javascript - var promise1 = RSVP.Promise.resolve(1); - var promise2 = RSVP.Promise.reject(new Error('2')); - var promise3 = RSVP.Promise.reject(new Error('3')); - var promises = [ promise1, promise2, promise3 ]; - - RSVP.allSettled(promises).then(function(array){ - // array == [ - // { state: 'fulfilled', value: 1 }, - // { state: 'rejected', reason: Error }, - // { state: 'rejected', reason: Error } - // ] - // Note that for the second item, reason.message will be '2', and for the - // third item, reason.message will be '3'. - }, function(error) { - // Not run. (This block would only be called if allSettled had failed, - // for instance if passed an incorrect argument type.) - }); - ``` - - @method allSettled - @static - @for RSVP - @param {Array} entries - @param {String} label - optional string that describes the promise. - Useful for tooling. - @return {Promise} promise that is fulfilled with an array of the settled - states of the constituent promises. -*/ - -function allSettled(entries, label) { - return new AllSettled(Promise, entries, label).promise; -} - -/** - This is a convenient alias for `RSVP.Promise.race`. - - @method race - @static - @for RSVP - @param {Array} array Array of promises. - @param {String} label An optional label. This is useful - for tooling. - */ -function race$1(array, label) { - return Promise.race(array, label); -} - -function PromiseHash(Constructor, object, label) { - this._superConstructor(Constructor, object, true, label); -} - -PromiseHash.prototype = o_create(Enumerator.prototype); -PromiseHash.prototype._superConstructor = Enumerator; -PromiseHash.prototype._init = function() { - this._result = {}; -}; - -PromiseHash.prototype._validateInput = function(input) { - return input && typeof input === 'object'; -}; - -PromiseHash.prototype._validationError = function() { - return new Error('Promise.hash must be called with an object'); -}; - -PromiseHash.prototype._enumerate = function() { - var enumerator = this; - var promise = enumerator.promise; - var input = enumerator._input; - var results = []; - - for (var key in input) { - if (promise._state === PENDING && Object.prototype.hasOwnProperty.call(input, key)) { - results.push({ - position: key, - entry: input[key] - }); - } + /** + This is a convenient alias for `RSVP.Promise.all`. + + @method all + @static + @for RSVP + @param {Array} array Array of promises. + @param {String} label An optional label. This is useful + for tooling. + */ + function all$1(array, label) { + return Promise.all(array, label); } - var length = results.length; - enumerator._remaining = length; - var result; - - for (var i = 0; promise._state === PENDING && i < length; i++) { - result = results[i]; - enumerator._eachEntry(result.entry, result.position); + function AllSettled(Constructor, entries, label) { + this._superConstructor(Constructor, entries, false, /* don't abort on reject */label); } -}; -/** - `RSVP.hash` is similar to `RSVP.all`, but takes an object instead of an array - for its `promises` argument. - - Returns a promise that is fulfilled when all the given promises have been - fulfilled, or rejected if any of them become rejected. The returned promise - is fulfilled with a hash that has the same key names as the `promises` object - argument. If any of the values in the object are not promises, they will - simply be copied over to the fulfilled object. - - Example: - - ```javascript - var promises = { - myPromise: RSVP.resolve(1), - yourPromise: RSVP.resolve(2), - theirPromise: RSVP.resolve(3), - notAPromise: 4 + AllSettled.prototype = o_create(Enumerator.prototype); + AllSettled.prototype._superConstructor = Enumerator; + AllSettled.prototype._makeResult = makeSettledResult; + AllSettled.prototype._validationError = function () { + return new Error('allSettled must be called with an array'); }; - RSVP.hash(promises).then(function(hash){ - // hash here is an object that looks like: - // { - // myPromise: 1, - // yourPromise: 2, - // theirPromise: 3, - // notAPromise: 4 - // } - }); - ```` + /** + `RSVP.allSettled` is similar to `RSVP.all`, but instead of implementing + a fail-fast method, it waits until all the promises have returned and + shows you all the results. This is useful if you want to handle multiple + promises' failure states together as a set. + + Returns a promise that is fulfilled when all the given promises have been + settled. The return promise is fulfilled with an array of the states of + the promises passed into the `promises` array argument. + + Each state object will either indicate fulfillment or rejection, and + provide the corresponding value or reason. The states will take one of + the following formats: + + ```javascript + { state: 'fulfilled', value: value } + or + { state: 'rejected', reason: reason } + ``` + + Example: + + ```javascript + let promise1 = RSVP.Promise.resolve(1); + let promise2 = RSVP.Promise.reject(new Error('2')); + let promise3 = RSVP.Promise.reject(new Error('3')); + let promises = [ promise1, promise2, promise3 ]; + + RSVP.allSettled(promises).then(function(array){ + // array == [ + // { state: 'fulfilled', value: 1 }, + // { state: 'rejected', reason: Error }, + // { state: 'rejected', reason: Error } + // ] + // Note that for the second item, reason.message will be '2', and for the + // third item, reason.message will be '3'. + }, function(error) { + // Not run. (This block would only be called if allSettled had failed, + // for instance if passed an incorrect argument type.) + }); + ``` + + @method allSettled + @static + @for RSVP + @param {Array} entries + @param {String} label - optional string that describes the promise. + Useful for tooling. + @return {Promise} promise that is fulfilled with an array of the settled + states of the constituent promises. + */ - If any of the `promises` given to `RSVP.hash` are rejected, the first promise - that is rejected will be given as the reason to the rejection handler. + function allSettled(entries, label) { + return new AllSettled(Promise, entries, label).promise; + } - Example: + /** + This is a convenient alias for `RSVP.Promise.race`. + + @method race + @static + @for RSVP + @param {Array} array Array of promises. + @param {String} label An optional label. This is useful + for tooling. + */ + function race$1(array, label) { + return Promise.race(array, label); + } - ```javascript - var promises = { - myPromise: RSVP.resolve(1), - rejectedPromise: RSVP.reject(new Error('rejectedPromise')), - anotherRejectedPromise: RSVP.reject(new Error('anotherRejectedPromise')), - }; - - RSVP.hash(promises).then(function(hash){ - // Code here never runs because there are rejected promises! - }, function(reason) { - // reason.message === 'rejectedPromise' - }); - ``` - - An important note: `RSVP.hash` is intended for plain JavaScript objects that - are just a set of keys and values. `RSVP.hash` will NOT preserve prototype - chains. - - Example: - - ```javascript - function MyConstructor(){ - this.example = RSVP.resolve('Example'); + function PromiseHash(Constructor, object, label) { + this._superConstructor(Constructor, object, true, label); } - MyConstructor.prototype = { - protoProperty: RSVP.resolve('Proto Property') + PromiseHash.prototype = o_create(Enumerator.prototype); + PromiseHash.prototype._superConstructor = Enumerator; + PromiseHash.prototype._init = function () { + this._result = {}; }; - var myObject = new MyConstructor(); + PromiseHash.prototype._validateInput = function (input) { + return input && typeof input === 'object'; + }; - RSVP.hash(myObject).then(function(hash){ - // protoProperty will not be present, instead you will just have an - // object that looks like: - // { - // example: 'Example' - // } - // - // hash.hasOwnProperty('protoProperty'); // false - // 'undefined' === typeof hash.protoProperty - }); - ``` - - @method hash - @static - @for RSVP - @param {Object} object - @param {String} label optional string that describes the promise. - Useful for tooling. - @return {Promise} promise that is fulfilled when all properties of `promises` - have been fulfilled, or rejected if any of them become rejected. -*/ -function hash(object, label) { - return new PromiseHash(Promise, object, label).promise; -} - -function HashSettled(Constructor, object, label) { - this._superConstructor(Constructor, object, false, label); -} - -HashSettled.prototype = o_create(PromiseHash.prototype); -HashSettled.prototype._superConstructor = Enumerator; -HashSettled.prototype._makeResult = makeSettledResult; - -HashSettled.prototype._validationError = function() { - return new Error('hashSettled must be called with an object'); -}; - -/** - `RSVP.hashSettled` is similar to `RSVP.allSettled`, but takes an object - instead of an array for its `promises` argument. - - Unlike `RSVP.all` or `RSVP.hash`, which implement a fail-fast method, - but like `RSVP.allSettled`, `hashSettled` waits until all the - constituent promises have returned and then shows you all the results - with their states and values/reasons. This is useful if you want to - handle multiple promises' failure states together as a set. - - Returns a promise that is fulfilled when all the given promises have been - settled, or rejected if the passed parameters are invalid. - - The returned promise is fulfilled with a hash that has the same key names as - the `promises` object argument. If any of the values in the object are not - promises, they will be copied over to the fulfilled object and marked with state - 'fulfilled'. - - Example: - - ```javascript - var promises = { - myPromise: RSVP.Promise.resolve(1), - yourPromise: RSVP.Promise.resolve(2), - theirPromise: RSVP.Promise.resolve(3), - notAPromise: 4 + PromiseHash.prototype._validationError = function () { + return new Error('Promise.hash must be called with an object'); }; - RSVP.hashSettled(promises).then(function(hash){ - // hash here is an object that looks like: - // { - // myPromise: { state: 'fulfilled', value: 1 }, - // yourPromise: { state: 'fulfilled', value: 2 }, - // theirPromise: { state: 'fulfilled', value: 3 }, - // notAPromise: { state: 'fulfilled', value: 4 } - // } - }); - ``` + PromiseHash.prototype._enumerate = function () { + var enumerator = this; + var promise = enumerator.promise; + var input = enumerator._input; + var results = []; - If any of the `promises` given to `RSVP.hash` are rejected, the state will - be set to 'rejected' and the reason for rejection provided. + for (var key in input) { + if (promise._state === PENDING && Object.prototype.hasOwnProperty.call(input, key)) { + results.push({ + position: key, + entry: input[key] + }); + } + } - Example: + var length = results.length; + enumerator._remaining = length; + var result = undefined; - ```javascript - var promises = { - myPromise: RSVP.Promise.resolve(1), - rejectedPromise: RSVP.Promise.reject(new Error('rejection')), - anotherRejectedPromise: RSVP.Promise.reject(new Error('more rejection')), + for (var i = 0; promise._state === PENDING && i < length; i++) { + result = results[i]; + enumerator._eachEntry(result.entry, result.position); + } }; - RSVP.hashSettled(promises).then(function(hash){ - // hash here is an object that looks like: - // { - // myPromise: { state: 'fulfilled', value: 1 }, - // rejectedPromise: { state: 'rejected', reason: Error }, - // anotherRejectedPromise: { state: 'rejected', reason: Error }, - // } - // Note that for rejectedPromise, reason.message == 'rejection', - // and for anotherRejectedPromise, reason.message == 'more rejection'. - }); - ``` + /** + `RSVP.hash` is similar to `RSVP.all`, but takes an object instead of an array + for its `promises` argument. + + Returns a promise that is fulfilled when all the given promises have been + fulfilled, or rejected if any of them become rejected. The returned promise + is fulfilled with a hash that has the same key names as the `promises` object + argument. If any of the values in the object are not promises, they will + simply be copied over to the fulfilled object. + + Example: + + ```javascript + let promises = { + myPromise: RSVP.resolve(1), + yourPromise: RSVP.resolve(2), + theirPromise: RSVP.resolve(3), + notAPromise: 4 + }; + + RSVP.hash(promises).then(function(hash){ + // hash here is an object that looks like: + // { + // myPromise: 1, + // yourPromise: 2, + // theirPromise: 3, + // notAPromise: 4 + // } + }); + ```` + + If any of the `promises` given to `RSVP.hash` are rejected, the first promise + that is rejected will be given as the reason to the rejection handler. + + Example: + + ```javascript + let promises = { + myPromise: RSVP.resolve(1), + rejectedPromise: RSVP.reject(new Error('rejectedPromise')), + anotherRejectedPromise: RSVP.reject(new Error('anotherRejectedPromise')), + }; + + RSVP.hash(promises).then(function(hash){ + // Code here never runs because there are rejected promises! + }, function(reason) { + // reason.message === 'rejectedPromise' + }); + ``` + + An important note: `RSVP.hash` is intended for plain JavaScript objects that + are just a set of keys and values. `RSVP.hash` will NOT preserve prototype + chains. + + Example: + + ```javascript + function MyConstructor(){ + this.example = RSVP.resolve('Example'); + } + + MyConstructor.prototype = { + protoProperty: RSVP.resolve('Proto Property') + }; + + let myObject = new MyConstructor(); + + RSVP.hash(myObject).then(function(hash){ + // protoProperty will not be present, instead you will just have an + // object that looks like: + // { + // example: 'Example' + // } + // + // hash.hasOwnProperty('protoProperty'); // false + // 'undefined' === typeof hash.protoProperty + }); + ``` + + @method hash + @static + @for RSVP + @param {Object} object + @param {String} label optional string that describes the promise. + Useful for tooling. + @return {Promise} promise that is fulfilled when all properties of `promises` + have been fulfilled, or rejected if any of them become rejected. + */ + function hash(object, label) { + return new PromiseHash(Promise, object, label).promise; + } - An important note: `RSVP.hashSettled` is intended for plain JavaScript objects that - are just a set of keys and values. `RSVP.hashSettled` will NOT preserve prototype - chains. - - Example: - - ```javascript - function MyConstructor(){ - this.example = RSVP.Promise.resolve('Example'); + function HashSettled(Constructor, object, label) { + this._superConstructor(Constructor, object, false, label); } - MyConstructor.prototype = { - protoProperty: RSVP.Promise.resolve('Proto Property') + HashSettled.prototype = o_create(PromiseHash.prototype); + HashSettled.prototype._superConstructor = Enumerator; + HashSettled.prototype._makeResult = makeSettledResult; + + HashSettled.prototype._validationError = function () { + return new Error('hashSettled must be called with an object'); }; - var myObject = new MyConstructor(); - - RSVP.hashSettled(myObject).then(function(hash){ - // protoProperty will not be present, instead you will just have an - // object that looks like: - // { - // example: { state: 'fulfilled', value: 'Example' } - // } - // - // hash.hasOwnProperty('protoProperty'); // false - // 'undefined' === typeof hash.protoProperty - }); - ``` - - @method hashSettled - @for RSVP - @param {Object} object - @param {String} label optional string that describes the promise. - Useful for tooling. - @return {Promise} promise that is fulfilled when when all properties of `promises` - have been settled. - @static -*/ -function hashSettled(object, label) { - return new HashSettled(Promise, object, label).promise; -} - -/** - `RSVP.rethrow` will rethrow an error on the next turn of the JavaScript event - loop in order to aid debugging. - - Promises A+ specifies that any exceptions that occur with a promise must be - caught by the promises implementation and bubbled to the last handler. For - this reason, it is recommended that you always specify a second rejection - handler function to `then`. However, `RSVP.rethrow` will throw the exception - outside of the promise, so it bubbles up to your console if in the browser, - or domain/cause uncaught exception in Node. `rethrow` will also throw the - error again so the error can be handled by the promise per the spec. - - ```javascript - function throws(){ - throw new Error('Whoops!'); + /** + `RSVP.hashSettled` is similar to `RSVP.allSettled`, but takes an object + instead of an array for its `promises` argument. + + Unlike `RSVP.all` or `RSVP.hash`, which implement a fail-fast method, + but like `RSVP.allSettled`, `hashSettled` waits until all the + constituent promises have returned and then shows you all the results + with their states and values/reasons. This is useful if you want to + handle multiple promises' failure states together as a set. + + Returns a promise that is fulfilled when all the given promises have been + settled, or rejected if the passed parameters are invalid. + + The returned promise is fulfilled with a hash that has the same key names as + the `promises` object argument. If any of the values in the object are not + promises, they will be copied over to the fulfilled object and marked with state + 'fulfilled'. + + Example: + + ```javascript + let promises = { + myPromise: RSVP.Promise.resolve(1), + yourPromise: RSVP.Promise.resolve(2), + theirPromise: RSVP.Promise.resolve(3), + notAPromise: 4 + }; + + RSVP.hashSettled(promises).then(function(hash){ + // hash here is an object that looks like: + // { + // myPromise: { state: 'fulfilled', value: 1 }, + // yourPromise: { state: 'fulfilled', value: 2 }, + // theirPromise: { state: 'fulfilled', value: 3 }, + // notAPromise: { state: 'fulfilled', value: 4 } + // } + }); + ``` + + If any of the `promises` given to `RSVP.hash` are rejected, the state will + be set to 'rejected' and the reason for rejection provided. + + Example: + + ```javascript + let promises = { + myPromise: RSVP.Promise.resolve(1), + rejectedPromise: RSVP.Promise.reject(new Error('rejection')), + anotherRejectedPromise: RSVP.Promise.reject(new Error('more rejection')), + }; + + RSVP.hashSettled(promises).then(function(hash){ + // hash here is an object that looks like: + // { + // myPromise: { state: 'fulfilled', value: 1 }, + // rejectedPromise: { state: 'rejected', reason: Error }, + // anotherRejectedPromise: { state: 'rejected', reason: Error }, + // } + // Note that for rejectedPromise, reason.message == 'rejection', + // and for anotherRejectedPromise, reason.message == 'more rejection'. + }); + ``` + + An important note: `RSVP.hashSettled` is intended for plain JavaScript objects that + are just a set of keys and values. `RSVP.hashSettled` will NOT preserve prototype + chains. + + Example: + + ```javascript + function MyConstructor(){ + this.example = RSVP.Promise.resolve('Example'); + } + + MyConstructor.prototype = { + protoProperty: RSVP.Promise.resolve('Proto Property') + }; + + let myObject = new MyConstructor(); + + RSVP.hashSettled(myObject).then(function(hash){ + // protoProperty will not be present, instead you will just have an + // object that looks like: + // { + // example: { state: 'fulfilled', value: 'Example' } + // } + // + // hash.hasOwnProperty('protoProperty'); // false + // 'undefined' === typeof hash.protoProperty + }); + ``` + + @method hashSettled + @for RSVP + @param {Object} object + @param {String} label optional string that describes the promise. + Useful for tooling. + @return {Promise} promise that is fulfilled when when all properties of `promises` + have been settled. + @static + */ + function hashSettled(object, label) { + return new HashSettled(Promise, object, label).promise; } - var promise = new RSVP.Promise(function(resolve, reject){ - throws(); - }); - - promise.catch(RSVP.rethrow).then(function(){ - // Code here doesn't run because the promise became rejected due to an - // error! - }, function (err){ - // handle the error here - }); - ``` - - The 'Whoops' error will be thrown on the next turn of the event loop - and you can watch for it in your console. You can also handle it using a - rejection handler given to `.then` or `.catch` on the returned promise. - - @method rethrow - @static - @for RSVP - @param {Error} reason reason the promise became rejected. - @throws Error - @static -*/ -function rethrow(reason) { - setTimeout(function() { + /** + `RSVP.rethrow` will rethrow an error on the next turn of the JavaScript event + loop in order to aid debugging. + + Promises A+ specifies that any exceptions that occur with a promise must be + caught by the promises implementation and bubbled to the last handler. For + this reason, it is recommended that you always specify a second rejection + handler function to `then`. However, `RSVP.rethrow` will throw the exception + outside of the promise, so it bubbles up to your console if in the browser, + or domain/cause uncaught exception in Node. `rethrow` will also throw the + error again so the error can be handled by the promise per the spec. + + ```javascript + function throws(){ + throw new Error('Whoops!'); + } + + let promise = new RSVP.Promise(function(resolve, reject){ + throws(); + }); + + promise.catch(RSVP.rethrow).then(function(){ + // Code here doesn't run because the promise became rejected due to an + // error! + }, function (err){ + // handle the error here + }); + ``` + + The 'Whoops' error will be thrown on the next turn of the event loop + and you can watch for it in your console. You can also handle it using a + rejection handler given to `.then` or `.catch` on the returned promise. + + @method rethrow + @static + @for RSVP + @param {Error} reason reason the promise became rejected. + @throws Error + @static + */ + function rethrow(reason) { + setTimeout(function () { + throw reason; + }); throw reason; - }); - throw reason; -} + } -/** - `RSVP.defer` returns an object similar to jQuery's `$.Deferred`. - `RSVP.defer` should be used when porting over code reliant on `$.Deferred`'s - interface. New code should use the `RSVP.Promise` constructor instead. + /** + `RSVP.defer` returns an object similar to jQuery's `$.Deferred`. + `RSVP.defer` should be used when porting over code reliant on `$.Deferred`'s + interface. New code should use the `RSVP.Promise` constructor instead. + + The object returned from `RSVP.defer` is a plain object with three properties: + + * promise - an `RSVP.Promise`. + * reject - a function that causes the `promise` property on this object to + become rejected + * resolve - a function that causes the `promise` property on this object to + become fulfilled. + + Example: + + ```javascript + let deferred = RSVP.defer(); + + deferred.resolve("Success!"); + + deferred.promise.then(function(value){ + // value here is "Success!" + }); + ``` + + @method defer + @static + @for RSVP + @param {String} label optional string for labeling the promise. + Useful for tooling. + @return {Object} + */ - The object returned from `RSVP.defer` is a plain object with three properties: + function defer(label) { + var deferred = { resolve: undefined, reject: undefined }; - * promise - an `RSVP.Promise`. - * reject - a function that causes the `promise` property on this object to - become rejected - * resolve - a function that causes the `promise` property on this object to - become fulfilled. + deferred.promise = new Promise(function (resolve, reject) { + deferred.resolve = resolve; + deferred.reject = reject; + }, label); - Example: + return deferred; + } - ```javascript - var deferred = RSVP.defer(); + /** + `RSVP.map` is similar to JavaScript's native `map` method, except that it + waits for all promises to become fulfilled before running the `mapFn` on + each item in given to `promises`. `RSVP.map` returns a promise that will + become fulfilled with the result of running `mapFn` on the values the promises + become fulfilled with. + + For example: + + ```javascript + + let promise1 = RSVP.resolve(1); + let promise2 = RSVP.resolve(2); + let promise3 = RSVP.resolve(3); + let promises = [ promise1, promise2, promise3 ]; + + let mapFn = function(item){ + return item + 1; + }; + + RSVP.map(promises, mapFn).then(function(result){ + // result is [ 2, 3, 4 ] + }); + ``` + + If any of the `promises` given to `RSVP.map` are rejected, the first promise + that is rejected will be given as an argument to the returned promise's + rejection handler. For example: + + ```javascript + let promise1 = RSVP.resolve(1); + let promise2 = RSVP.reject(new Error('2')); + let promise3 = RSVP.reject(new Error('3')); + let promises = [ promise1, promise2, promise3 ]; + + let mapFn = function(item){ + return item + 1; + }; + + RSVP.map(promises, mapFn).then(function(array){ + // Code here never runs because there are rejected promises! + }, function(reason) { + // reason.message === '2' + }); + ``` + + `RSVP.map` will also wait if a promise is returned from `mapFn`. For example, + say you want to get all comments from a set of blog posts, but you need + the blog posts first because they contain a url to those comments. + + ```javscript + + let mapFn = function(blogPost){ + // getComments does some ajax and returns an RSVP.Promise that is fulfilled + // with some comments data + return getComments(blogPost.comments_url); + }; + + // getBlogPosts does some ajax and returns an RSVP.Promise that is fulfilled + // with some blog post data + RSVP.map(getBlogPosts(), mapFn).then(function(comments){ + // comments is the result of asking the server for the comments + // of all blog posts returned from getBlogPosts() + }); + ``` + + @method map + @static + @for RSVP + @param {Array} promises + @param {Function} mapFn function to be called on each fulfilled promise. + @param {String} label optional string for labeling the promise. + Useful for tooling. + @return {Promise} promise that is fulfilled with the result of calling + `mapFn` on each fulfilled promise or value when they become fulfilled. + The promise will be rejected if any of the given `promises` become rejected. + @static + */ + function map(promises, mapFn, label) { + return Promise.all(promises, label).then(function (values) { + if (!isFunction(mapFn)) { + throw new TypeError("You must pass a function as map's second argument."); + } - deferred.resolve("Success!"); + var length = values.length; + var results = new Array(length); - deferred.promise.then(function(value){ - // value here is "Success!" - }); - ``` + for (var i = 0; i < length; i++) { + results[i] = mapFn(values[i]); + } - @method defer - @static - @for RSVP - @param {String} label optional string for labeling the promise. - Useful for tooling. - @return {Object} - */ + return Promise.all(results, label); + }); + } -function defer(label) { - var deferred = {}; + /** + This is a convenient alias for `RSVP.Promise.resolve`. + + @method resolve + @static + @for RSVP + @param {*} value value that the returned promise will be resolved with + @param {String} label optional string for identifying the returned promise. + Useful for tooling. + @return {Promise} a promise that will become fulfilled with the given + `value` + */ + function resolve$2(value, label) { + return Promise.resolve(value, label); + } - deferred['promise'] = new Promise(function(resolve, reject) { - deferred['resolve'] = resolve; - deferred['reject'] = reject; - }, label); + /** + This is a convenient alias for `RSVP.Promise.reject`. + + @method reject + @static + @for RSVP + @param {*} reason value that the returned promise will be rejected with. + @param {String} label optional string for identifying the returned promise. + Useful for tooling. + @return {Promise} a promise rejected with the given `reason`. + */ + function reject$2(reason, label) { + return Promise.reject(reason, label); + } - return deferred; -} + /** + `RSVP.filter` is similar to JavaScript's native `filter` method, except that it + waits for all promises to become fulfilled before running the `filterFn` on + each item in given to `promises`. `RSVP.filter` returns a promise that will + become fulfilled with the result of running `filterFn` on the values the + promises become fulfilled with. + + For example: + + ```javascript + + let promise1 = RSVP.resolve(1); + let promise2 = RSVP.resolve(2); + let promise3 = RSVP.resolve(3); + + let promises = [promise1, promise2, promise3]; + + let filterFn = function(item){ + return item > 1; + }; + + RSVP.filter(promises, filterFn).then(function(result){ + // result is [ 2, 3 ] + }); + ``` + + If any of the `promises` given to `RSVP.filter` are rejected, the first promise + that is rejected will be given as an argument to the returned promise's + rejection handler. For example: + + ```javascript + let promise1 = RSVP.resolve(1); + let promise2 = RSVP.reject(new Error('2')); + let promise3 = RSVP.reject(new Error('3')); + let promises = [ promise1, promise2, promise3 ]; + + let filterFn = function(item){ + return item > 1; + }; + + RSVP.filter(promises, filterFn).then(function(array){ + // Code here never runs because there are rejected promises! + }, function(reason) { + // reason.message === '2' + }); + ``` + + `RSVP.filter` will also wait for any promises returned from `filterFn`. + For instance, you may want to fetch a list of users then return a subset + of those users based on some asynchronous operation: + + ```javascript + + let alice = { name: 'alice' }; + let bob = { name: 'bob' }; + let users = [ alice, bob ]; + + let promises = users.map(function(user){ + return RSVP.resolve(user); + }); + + let filterFn = function(user){ + // Here, Alice has permissions to create a blog post, but Bob does not. + return getPrivilegesForUser(user).then(function(privs){ + return privs.can_create_blog_post === true; + }); + }; + RSVP.filter(promises, filterFn).then(function(users){ + // true, because the server told us only Alice can create a blog post. + users.length === 1; + // false, because Alice is the only user present in `users` + users[0] === bob; + }); + ``` + + @method filter + @static + @for RSVP + @param {Array} promises + @param {Function} filterFn - function to be called on each resolved value to + filter the final results. + @param {String} label optional string describing the promise. Useful for + tooling. + @return {Promise} + */ -/** - `RSVP.map` is similar to JavaScript's native `map` method, except that it - waits for all promises to become fulfilled before running the `mapFn` on - each item in given to `promises`. `RSVP.map` returns a promise that will - become fulfilled with the result of running `mapFn` on the values the promises - become fulfilled with. + function resolveAll(promises, label) { + return Promise.all(promises, label); + } - For example: + function resolveSingle(promise, label) { + return Promise.resolve(promise, label).then(function (promises) { + return resolveAll(promises, label); + }); + } - ```javascript + function filter(promises, filterFn, label) { + var promise = isArray(promises) ? resolveAll(promises, label) : resolveSingle(promises, label); + return promise.then(function (values) { + if (!isFunction(filterFn)) { + throw new TypeError("You must pass a function as filter's second argument."); + } - var promise1 = RSVP.resolve(1); - var promise2 = RSVP.resolve(2); - var promise3 = RSVP.resolve(3); - var promises = [ promise1, promise2, promise3 ]; + var length = values.length; + var filtered = new Array(length); - var mapFn = function(item){ - return item + 1; - }; + for (var i = 0; i < length; i++) { + filtered[i] = filterFn(values[i]); + } - RSVP.map(promises, mapFn).then(function(result){ - // result is [ 2, 3, 4 ] - }); - ``` + return resolveAll(filtered, label).then(function (filtered) { + var results = new Array(length); + var newLength = 0; - If any of the `promises` given to `RSVP.map` are rejected, the first promise - that is rejected will be given as an argument to the returned promise's - rejection handler. For example: + for (var i = 0; i < length; i++) { + if (filtered[i]) { + results[newLength] = values[i]; + newLength++; + } + } - ```javascript - var promise1 = RSVP.resolve(1); - var promise2 = RSVP.reject(new Error('2')); - var promise3 = RSVP.reject(new Error('3')); - var promises = [ promise1, promise2, promise3 ]; + results.length = newLength; - var mapFn = function(item){ - return item + 1; - }; + return results; + }); + }); + } - RSVP.map(promises, mapFn).then(function(array){ - // Code here never runs because there are rejected promises! - }, function(reason) { - // reason.message === '2' - }); - ``` + var len = 0; + var vertxNext = undefined; + function asap(callback, arg) { + queue$1[len] = callback; + queue$1[len + 1] = arg; + len += 2; + if (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. + scheduleFlush$1(); + } + } - `RSVP.map` will also wait if a promise is returned from `mapFn`. For example, - say you want to get all comments from a set of blog posts, but you need - the blog posts first because they contain a url to those comments. + var browserWindow = typeof window !== 'undefined' ? window : undefined; + var browserGlobal = browserWindow || {}; + var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver; + var isNode = typeof self === 'undefined' && typeof process !== 'undefined' && ({}).toString.call(process) === '[object process]'; - ```javscript + // test for web worker but not in IE10 + var isWorker = typeof Uint8ClampedArray !== 'undefined' && typeof importScripts !== 'undefined' && typeof MessageChannel !== 'undefined'; - var mapFn = function(blogPost){ - // getComments does some ajax and returns an RSVP.Promise that is fulfilled - // with some comments data - return getComments(blogPost.comments_url); - }; - - // getBlogPosts does some ajax and returns an RSVP.Promise that is fulfilled - // with some blog post data - RSVP.map(getBlogPosts(), mapFn).then(function(comments){ - // comments is the result of asking the server for the comments - // of all blog posts returned from getBlogPosts() - }); - ``` - - @method map - @static - @for RSVP - @param {Array} promises - @param {Function} mapFn function to be called on each fulfilled promise. - @param {String} label optional string for labeling the promise. - Useful for tooling. - @return {Promise} promise that is fulfilled with the result of calling - `mapFn` on each fulfilled promise or value when they become fulfilled. - The promise will be rejected if any of the given `promises` become rejected. - @static -*/ -function map(promises, mapFn, label) { - return Promise.all(promises, label).then(function(values) { - if (!isFunction(mapFn)) { - throw new TypeError("You must pass a function as map's second argument."); + // node + function useNextTick() { + var nextTick = process.nextTick; + // node version 0.10.x displays a deprecation warning when nextTick is used recursively + // setImmediate should be used instead instead + var version = process.versions.node.match(/^(?:(\d+)\.)?(?:(\d+)\.)?(\*|\d+)$/); + if (Array.isArray(version) && version[1] === '0' && version[2] === '10') { + nextTick = setImmediate; } + return function () { + return nextTick(flush); + }; + } - var length = values.length; - var results = new Array(length); - - for (var i = 0; i < length; i++) { - results[i] = mapFn(values[i]); + // vertx + function useVertxTimer() { + if (typeof vertxNext !== 'undefined') { + return function () { + vertxNext(flush); + }; } + return useSetTimeout(); + } - return Promise.all(results, label); - }); -} + function useMutationObserver() { + var iterations = 0; + var observer = new BrowserMutationObserver(flush); + var node = document.createTextNode(''); + observer.observe(node, { characterData: true }); -/** - This is a convenient alias for `RSVP.Promise.resolve`. + return function () { + return node.data = iterations = ++iterations % 2; + }; + } - @method resolve - @static - @for RSVP - @param {*} value value that the returned promise will be resolved with - @param {String} label optional string for identifying the returned promise. - Useful for tooling. - @return {Promise} a promise that will become fulfilled with the given - `value` -*/ -function resolve$2(value, label) { - return Promise.resolve(value, label); -} + // web worker + function useMessageChannel() { + var channel = new MessageChannel(); + channel.port1.onmessage = flush; + return function () { + return channel.port2.postMessage(0); + }; + } -/** - This is a convenient alias for `RSVP.Promise.reject`. + function useSetTimeout() { + return function () { + return setTimeout(flush, 1); + }; + } - @method reject - @static - @for RSVP - @param {*} reason value that the returned promise will be rejected with. - @param {String} label optional string for identifying the returned promise. - Useful for tooling. - @return {Promise} a promise rejected with the given `reason`. -*/ -function reject$2(reason, label) { - return Promise.reject(reason, label); -} + var queue$1 = new Array(1000); -/** - `RSVP.filter` is similar to JavaScript's native `filter` method, except that it - waits for all promises to become fulfilled before running the `filterFn` on - each item in given to `promises`. `RSVP.filter` returns a promise that will - become fulfilled with the result of running `filterFn` on the values the - promises become fulfilled with. + function flush() { + for (var i = 0; i < len; i += 2) { + var callback = queue$1[i]; + var arg = queue$1[i + 1]; - For example: + callback(arg); - ```javascript - - var promise1 = RSVP.resolve(1); - var promise2 = RSVP.resolve(2); - var promise3 = RSVP.resolve(3); - - var promises = [promise1, promise2, promise3]; - - var filterFn = function(item){ - return item > 1; - }; - - RSVP.filter(promises, filterFn).then(function(result){ - // result is [ 2, 3 ] - }); - ``` - - If any of the `promises` given to `RSVP.filter` are rejected, the first promise - that is rejected will be given as an argument to the returned promise's - rejection handler. For example: - - ```javascript - var promise1 = RSVP.resolve(1); - var promise2 = RSVP.reject(new Error('2')); - var promise3 = RSVP.reject(new Error('3')); - var promises = [ promise1, promise2, promise3 ]; - - var filterFn = function(item){ - return item > 1; - }; - - RSVP.filter(promises, filterFn).then(function(array){ - // Code here never runs because there are rejected promises! - }, function(reason) { - // reason.message === '2' - }); - ``` - - `RSVP.filter` will also wait for any promises returned from `filterFn`. - For instance, you may want to fetch a list of users then return a subset - of those users based on some asynchronous operation: - - ```javascript - - var alice = { name: 'alice' }; - var bob = { name: 'bob' }; - var users = [ alice, bob ]; - - var promises = users.map(function(user){ - return RSVP.resolve(user); - }); - - var filterFn = function(user){ - // Here, Alice has permissions to create a blog post, but Bob does not. - return getPrivilegesForUser(user).then(function(privs){ - return privs.can_create_blog_post === true; - }); - }; - RSVP.filter(promises, filterFn).then(function(users){ - // true, because the server told us only Alice can create a blog post. - users.length === 1; - // false, because Alice is the only user present in `users` - users[0] === bob; - }); - ``` - - @method filter - @static - @for RSVP - @param {Array} promises - @param {Function} filterFn - function to be called on each resolved value to - filter the final results. - @param {String} label optional string describing the promise. Useful for - tooling. - @return {Promise} -*/ -function filter(promises, filterFn, label) { - return Promise.all(promises, label).then(function(values) { - if (!isFunction(filterFn)) { - throw new TypeError("You must pass a function as filter's second argument."); + queue$1[i] = undefined; + queue$1[i + 1] = undefined; } - var length = values.length; - var filtered = new Array(length); + len = 0; + } - for (var i = 0; i < length; i++) { - filtered[i] = filterFn(values[i]); + function attemptVertex() { + try { + var r = require; + var vertx = r('vertx'); + vertxNext = vertx.runOnLoop || vertx.runOnContext; + return useVertxTimer(); + } catch (e) { + return useSetTimeout(); } - - return Promise.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 len = 0; -var vertxNext; -function asap(callback, arg) { - queue$1[len] = callback; - queue$1[len + 1] = arg; - len += 2; - if (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. - scheduleFlush$1(); } -} -var browserWindow = (typeof window !== 'undefined') ? window : undefined; -var browserGlobal = browserWindow || {}; -var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver; -var isNode = typeof self === 'undefined' && - typeof process !== 'undefined' && {}.toString.call(process) === '[object process]'; - -// test for web worker but not in IE10 -var isWorker = typeof Uint8ClampedArray !== 'undefined' && - typeof importScripts !== 'undefined' && - typeof MessageChannel !== 'undefined'; - -// node -function useNextTick() { - var nextTick = process.nextTick; - // node version 0.10.x displays a deprecation warning when nextTick is used recursively - // setImmediate should be used instead instead - var version = process.versions.node.match(/^(?:(\d+)\.)?(?:(\d+)\.)?(\*|\d+)$/); - if (Array.isArray(version) && version[1] === '0' && version[2] === '10') { - nextTick = setImmediate; + var scheduleFlush$1 = undefined; + // Decide what async method to use to triggering processing of queued callbacks: + if (isNode) { + scheduleFlush$1 = useNextTick(); + } else if (BrowserMutationObserver) { + scheduleFlush$1 = useMutationObserver(); + } else if (isWorker) { + scheduleFlush$1 = useMessageChannel(); + } else if (browserWindow === undefined && typeof require === 'function') { + scheduleFlush$1 = attemptVertex(); + } else { + scheduleFlush$1 = useSetTimeout(); } - return function() { - nextTick(flush); - }; -} -// vertx -function useVertxTimer() { - return function() { - vertxNext(flush); - }; -} + var platform = undefined; -function useMutationObserver() { - var iterations = 0; - var observer = new BrowserMutationObserver(flush); - var node = document.createTextNode(''); - observer.observe(node, { characterData: true }); + /* global self */ + if (typeof self === 'object') { + platform = self; - return function() { - node.data = (iterations = ++iterations % 2); - }; -} + /* global global */ + } else if (typeof global === 'object') { + platform = global; + } else { + throw new Error('no global: `self` or `global` found'); + } -// web worker -function useMessageChannel() { - var channel = new MessageChannel(); - channel.port1.onmessage = flush; - return function () { - channel.port2.postMessage(0); + // defaults + config.async = asap; + config.after = function (cb) { + return setTimeout(cb, 0); }; -} + var cast = resolve$2; -function useSetTimeout() { - return function() { - setTimeout(flush, 1); + var async = function (callback, arg) { + return config.async(callback, arg); }; -} -var queue$1 = new Array(1000); -function flush() { - for (var i = 0; i < len; i+=2) { - var callback = queue$1[i]; - var arg = queue$1[i+1]; - - callback(arg); - - queue$1[i] = undefined; - queue$1[i+1] = undefined; + function on() { + config['on'].apply(config, arguments); } - len = 0; -} - -function attemptVertex() { - try { - var r = require; - var vertx = r('vertx'); - vertxNext = vertx.runOnLoop || vertx.runOnContext; - return useVertxTimer(); - } catch(e) { - return useSetTimeout(); + function off() { + config['off'].apply(config, arguments); } -} -var scheduleFlush$1; -// Decide what async method to use to triggering processing of queued callbacks: -if (isNode) { - scheduleFlush$1 = useNextTick(); -} else if (BrowserMutationObserver) { - scheduleFlush$1 = useMutationObserver(); -} else if (isWorker) { - scheduleFlush$1 = useMessageChannel(); -} else if (browserWindow === undefined && typeof require === 'function') { - scheduleFlush$1 = attemptVertex(); -} else { - scheduleFlush$1 = useSetTimeout(); -} - -// defaults -config.async = asap; -config.after = function(cb) { - setTimeout(cb, 0); -}; -var cast = resolve$2; -function async(callback, arg) { - config.async(callback, arg); -} - -function on() { - config['on'].apply(config, arguments); -} - -function off() { - config['off'].apply(config, arguments); -} - -// Set up instrumentation through `window.__PROMISE_INTRUMENTATION__` -if (typeof window !== 'undefined' && typeof window['__PROMISE_INSTRUMENTATION__'] === 'object') { - var callbacks = window['__PROMISE_INSTRUMENTATION__']; - configure('instrument', true); - for (var eventName in callbacks) { - if (callbacks.hasOwnProperty(eventName)) { - on(eventName, callbacks[eventName]); + // Set up instrumentation through `window.__PROMISE_INTRUMENTATION__` + if (typeof window !== 'undefined' && typeof window['__PROMISE_INSTRUMENTATION__'] === 'object') { + var callbacks = window['__PROMISE_INSTRUMENTATION__']; + configure('instrument', true); + for (var eventName in callbacks) { + if (callbacks.hasOwnProperty(eventName)) { + on(eventName, callbacks[eventName]); + } } } -} -exports.cast = cast; -exports.Promise = Promise; -exports.EventTarget = EventTarget; -exports.all = all$1; -exports.allSettled = allSettled; -exports.race = race$1; -exports.hash = hash; -exports.hashSettled = hashSettled; -exports.rethrow = rethrow; -exports.defer = defer; -exports.denodeify = denodeify; -exports.configure = configure; -exports.on = on; -exports.off = off; -exports.resolve = resolve$2; -exports.reject = reject$2; -exports.async = async; -exports.map = map; -exports.filter = filter; + // the default export here is for backwards compat: + // https://github.com/tildeio/rsvp.js/issues/434 + var rsvp = (_rsvp = { + cast: cast, + Promise: Promise, + EventTarget: EventTarget, + all: all$1, + allSettled: allSettled, + race: race$1, + hash: hash, + hashSettled: hashSettled, + rethrow: rethrow, + defer: defer, + denodeify: denodeify, + configure: configure, + on: on, + off: off, + resolve: resolve$2, + reject: reject$2, + map: map + }, _rsvp['async'] = async, _rsvp.filter = // babel seems to error if async isn't a computed prop here... + filter, _rsvp); -Object.defineProperty(exports, '__esModule', { value: true }); - + exports.cast = cast; + exports.Promise = Promise; + exports.EventTarget = EventTarget; + exports.all = all$1; + exports.allSettled = allSettled; + exports.race = race$1; + exports.hash = hash; + exports.hashSettled = hashSettled; + exports.rethrow = rethrow; + exports.defer = defer; + exports.denodeify = denodeify; + exports.configure = configure; + exports.on = on; + exports.off = off; + exports.resolve = resolve$2; + exports.reject = reject$2; + exports.map = map; + exports.async = async; + exports.filter = filter; + exports.default = rsvp; }); (function (m) { if (typeof module === "object" && module.exports) { module.exports = m } }(requireModule("ember-runtime").default)); }());