ember-source 1.0.0.rc3.5 → 1.0.0.rc4

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of ember-source might be problematic. Click here for more details.

data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.0-rc4
@@ -1,5 +1,5 @@
1
- // Version: v1.0.0-rc.3-2-g85bfdbf
2
- // Last commit: 85bfdbf (2013-07-25 20:16:20 -0400)
1
+ // Version: v1.0.0-rc4
2
+ // Last commit: ae2e55f (2013-05-27 19:34:11 -0400)
3
3
 
4
4
 
5
5
  (function() {
@@ -151,8 +151,8 @@ Ember.deprecateFunc = function(message, func) {
151
151
 
152
152
  })();
153
153
 
154
- // Version: v1.0.0-rc.3-2-g85bfdbf
155
- // Last commit: 85bfdbf (2013-07-25 20:16:20 -0400)
154
+ // Version: v1.0.0-rc4
155
+ // Last commit: ae2e55f (2013-05-27 19:34:11 -0400)
156
156
 
157
157
 
158
158
  (function() {
@@ -169,11 +169,18 @@ var define, requireModule;
169
169
  if (seen[name]) { return seen[name]; }
170
170
  seen[name] = {};
171
171
 
172
- var mod = registry[name],
173
- deps = mod.deps,
174
- callback = mod.callback,
175
- reified = [],
176
- exports;
172
+ var mod, deps, callback, reified, exports;
173
+
174
+ mod = registry[name];
175
+
176
+ if (!mod) {
177
+ throw new Error("Module '" + name + "' not found.");
178
+ }
179
+
180
+ deps = mod.deps;
181
+ callback = mod.callback;
182
+ reified = [];
183
+ exports;
177
184
 
178
185
  for (var i=0, l=deps.length; i<l; i++) {
179
186
  if (deps[i] === 'exports') {
@@ -212,7 +219,7 @@ var define, requireModule;
212
219
 
213
220
  @class Ember
214
221
  @static
215
- @version 1.0.0-rc.3
222
+ @version 1.0.0-rc4
216
223
  */
217
224
 
218
225
  if ('undefined' === typeof Ember) {
@@ -239,10 +246,10 @@ Ember.toString = function() { return "Ember"; };
239
246
  /**
240
247
  @property VERSION
241
248
  @type String
242
- @default '1.0.0-rc.3'
249
+ @default '1.0.0-rc4'
243
250
  @final
244
251
  */
245
- Ember.VERSION = '1.0.0-rc.3';
252
+ Ember.VERSION = '1.0.0-rc4';
246
253
 
247
254
  /**
248
255
  Standard environmental variables. You can define these in a global `ENV`
@@ -391,7 +398,7 @@ Ember.onerror = null;
391
398
  /**
392
399
  @private
393
400
 
394
- Wrap code block in a try/catch if {{#crossLink "Ember/onerror"}}{{/crossLink}} is set.
401
+ Wrap code block in a try/catch if `Ember.onerror` is set.
395
402
 
396
403
  @method handleErrors
397
404
  @for Ember
@@ -467,7 +474,7 @@ Ember.none = Ember.deprecateFunc("Ember.none is deprecated. Please use Ember.isN
467
474
  @return {Boolean}
468
475
  */
469
476
  Ember.isEmpty = function(obj) {
470
- return obj === null || obj === undefined || (obj.length === 0 && typeof obj !== 'function') || (typeof obj === 'object' && Ember.get(obj, 'length') === 0);
477
+ return Ember.isNone(obj) || (obj.length === 0 && typeof obj !== 'function') || (typeof obj === 'object' && Ember.get(obj, 'length') === 0);
471
478
  };
472
479
  Ember.empty = Ember.deprecateFunc("Ember.empty is deprecated. Please use Ember.isEmpty instead.", Ember.isEmpty) ;
473
480
 
@@ -500,6 +507,13 @@ var platform = Ember.platform = {};
500
507
  */
501
508
  Ember.create = Object.create;
502
509
 
510
+ // IE8 has Object.create but it couldn't treat property descripters.
511
+ if (Ember.create) {
512
+ if (Ember.create({a: 1}, {a: {value: 2}}).a !== 2) {
513
+ Ember.create = null;
514
+ }
515
+ }
516
+
503
517
  // STUB_OBJECT_CREATE allows us to override other libraries that stub
504
518
  // Object.create different than we would prefer
505
519
  if (!Ember.create || Ember.ENV.STUB_OBJECT_CREATE) {
@@ -820,7 +834,7 @@ Ember.guidFor = function guidFor(obj) {
820
834
  if (obj === undefined) return "(undefined)";
821
835
  if (obj === null) return "(null)";
822
836
 
823
- var cache, ret;
837
+ var ret;
824
838
  var type = typeof obj;
825
839
 
826
840
  // Don't allow prototype changes to String etc. to change the guidFor
@@ -969,6 +983,7 @@ Ember.setMeta = function setMeta(obj, property, value) {
969
983
  };
970
984
 
971
985
  /**
986
+ @deprecated
972
987
  @private
973
988
 
974
989
  In order to store defaults for a class, a prototype may need to create
@@ -1001,6 +1016,7 @@ Ember.setMeta = function setMeta(obj, property, value) {
1001
1016
  shared with its constructor
1002
1017
  */
1003
1018
  Ember.metaPath = function metaPath(obj, path, writable) {
1019
+ Ember.deprecate("Ember.metaPath is deprecated and will be removed from future releases.");
1004
1020
  var meta = Ember.meta(obj, writable), keyName, value;
1005
1021
 
1006
1022
  for (var i=0, l=path.length; i<l; i++) {
@@ -1221,7 +1237,7 @@ if (needsFinallyFix) {
1221
1237
  */
1222
1238
  if (needsFinallyFix) {
1223
1239
  Ember.tryCatchFinally = function(tryable, catchable, finalizer, binding) {
1224
- var result, finalResult, finalError, finalReturn;
1240
+ var result, finalResult, finalError;
1225
1241
 
1226
1242
  binding = binding || this;
1227
1243
 
@@ -1331,6 +1347,7 @@ Ember.typeOf = function(item) {
1331
1347
 
1332
1348
  return ret;
1333
1349
  };
1350
+
1334
1351
  })();
1335
1352
 
1336
1353
 
@@ -1577,816 +1594,454 @@ var utils = Ember.EnumerableUtils = {
1577
1594
  @module ember-metal
1578
1595
  */
1579
1596
 
1580
- /*
1581
- JavaScript (before ES6) does not have a Map implementation. Objects,
1582
- which are often used as dictionaries, may only have Strings as keys.
1583
-
1584
- Because Ember has a way to get a unique identifier for every object
1585
- via `Ember.guidFor`, we can implement a performant Map with arbitrary
1586
- keys. Because it is commonly used in low-level bookkeeping, Map is
1587
- implemented as a pure JavaScript object for performance.
1588
-
1589
- This implementation follows the current iteration of the ES6 proposal for
1590
- maps (http://wiki.ecmascript.org/doku.php?id=harmony:simple_maps_and_sets),
1591
- with two exceptions. First, because we need our implementation to be pleasant
1592
- on older browsers, we do not use the `delete` name (using `remove` instead).
1593
- Second, as we do not have the luxury of in-VM iteration, we implement a
1594
- forEach method for iteration.
1595
-
1596
- Map is mocked out to look like an Ember object, so you can do
1597
- `Ember.Map.create()` for symmetry with other Ember classes.
1598
- */
1599
- var guidFor = Ember.guidFor,
1600
- indexOf = Ember.ArrayPolyfills.indexOf;
1597
+ var META_KEY = Ember.META_KEY, get;
1601
1598
 
1602
- var copy = function(obj) {
1603
- var output = {};
1599
+ var MANDATORY_SETTER = Ember.ENV.MANDATORY_SETTER;
1604
1600
 
1605
- for (var prop in obj) {
1606
- if (obj.hasOwnProperty(prop)) { output[prop] = obj[prop]; }
1607
- }
1601
+ var IS_GLOBAL_PATH = /^([A-Z$]|([0-9][A-Z$])).*[\.\*]/;
1602
+ var HAS_THIS = /^this[\.\*]/;
1603
+ var FIRST_KEY = /^([^\.\*]+)/;
1608
1604
 
1609
- return output;
1610
- };
1605
+ // ..........................................................
1606
+ // GET AND SET
1607
+ //
1608
+ // If we are on a platform that supports accessors we can use those.
1609
+ // Otherwise simulate accessors by looking up the property directly on the
1610
+ // object.
1611
1611
 
1612
- var copyMap = function(original, newObject) {
1613
- var keys = original.keys.copy(),
1614
- values = copy(original.values);
1612
+ /**
1613
+ Gets the value of a property on an object. If the property is computed,
1614
+ the function will be invoked. If the property is not defined but the
1615
+ object implements the `unknownProperty` method then that will be invoked.
1615
1616
 
1616
- newObject.keys = keys;
1617
- newObject.values = values;
1617
+ If you plan to run on IE8 and older browsers then you should use this
1618
+ method anytime you want to retrieve a property on an object that you don't
1619
+ know for sure is private. (Properties beginning with an underscore '_'
1620
+ are considered private.)
1618
1621
 
1619
- return newObject;
1620
- };
1622
+ On all newer browsers, you only need to use this method to retrieve
1623
+ properties if the property might not be defined on the object and you want
1624
+ to respect the `unknownProperty` handler. Otherwise you can ignore this
1625
+ method.
1621
1626
 
1622
- /**
1623
- This class is used internally by Ember and Ember Data.
1624
- Please do not use it at this time. We plan to clean it up
1625
- and add many tests soon.
1627
+ Note that if the object itself is `undefined`, this method will throw
1628
+ an error.
1626
1629
 
1627
- @class OrderedSet
1628
- @namespace Ember
1629
- @constructor
1630
- @private
1630
+ @method get
1631
+ @for Ember
1632
+ @param {Object} obj The object to retrieve from.
1633
+ @param {String} keyName The property key to retrieve
1634
+ @return {Object} the property value or `null`.
1631
1635
  */
1632
- var OrderedSet = Ember.OrderedSet = function() {
1633
- this.clear();
1634
- };
1636
+ get = function get(obj, keyName) {
1637
+ // Helpers that operate with 'this' within an #each
1638
+ if (keyName === '') {
1639
+ return obj;
1640
+ }
1635
1641
 
1636
- /**
1637
- @method create
1638
- @static
1639
- @return {Ember.OrderedSet}
1640
- */
1641
- OrderedSet.create = function() {
1642
- return new OrderedSet();
1643
- };
1642
+ if (!keyName && 'string'===typeof obj) {
1643
+ keyName = obj;
1644
+ obj = null;
1645
+ }
1644
1646
 
1647
+ Ember.assert("Cannot call get with '"+ keyName +"' on an undefined object.", obj !== undefined);
1645
1648
 
1646
- OrderedSet.prototype = {
1647
- /**
1648
- @method clear
1649
- */
1650
- clear: function() {
1651
- this.presenceSet = {};
1652
- this.list = [];
1653
- },
1649
+ if (obj === null || keyName.indexOf('.') !== -1) {
1650
+ return getPath(obj, keyName);
1651
+ }
1654
1652
 
1655
- /**
1656
- @method add
1657
- @param obj
1658
- */
1659
- add: function(obj) {
1660
- var guid = guidFor(obj),
1661
- presenceSet = this.presenceSet,
1662
- list = this.list;
1653
+ var meta = obj[META_KEY], desc = meta && meta.descs[keyName], ret;
1654
+ if (desc) {
1655
+ return desc.get(obj, keyName);
1656
+ } else {
1657
+ if (MANDATORY_SETTER && meta && meta.watching[keyName] > 0) {
1658
+ ret = meta.values[keyName];
1659
+ } else {
1660
+ ret = obj[keyName];
1661
+ }
1663
1662
 
1664
- if (guid in presenceSet) { return; }
1663
+ if (ret === undefined &&
1664
+ 'object' === typeof obj && !(keyName in obj) && 'function' === typeof obj.unknownProperty) {
1665
+ return obj.unknownProperty(keyName);
1666
+ }
1665
1667
 
1666
- presenceSet[guid] = true;
1667
- list.push(obj);
1668
- },
1668
+ return ret;
1669
+ }
1670
+ };
1669
1671
 
1670
- /**
1671
- @method remove
1672
- @param obj
1673
- */
1674
- remove: function(obj) {
1675
- var guid = guidFor(obj),
1676
- presenceSet = this.presenceSet,
1677
- list = this.list;
1672
+ // Currently used only by Ember Data tests
1673
+ if (Ember.config.overrideAccessors) {
1674
+ Ember.get = get;
1675
+ Ember.config.overrideAccessors();
1676
+ get = Ember.get;
1677
+ }
1678
1678
 
1679
- delete presenceSet[guid];
1679
+ function firstKey(path) {
1680
+ return path.match(FIRST_KEY)[0];
1681
+ }
1680
1682
 
1681
- var index = indexOf.call(list, obj);
1682
- if (index > -1) {
1683
- list.splice(index, 1);
1684
- }
1685
- },
1683
+ // assumes path is already normalized
1684
+ function normalizeTuple(target, path) {
1685
+ var hasThis = HAS_THIS.test(path),
1686
+ isGlobal = !hasThis && IS_GLOBAL_PATH.test(path),
1687
+ key;
1686
1688
 
1687
- /**
1688
- @method isEmpty
1689
- @return {Boolean}
1690
- */
1691
- isEmpty: function() {
1692
- return this.list.length === 0;
1693
- },
1689
+ if (!target || isGlobal) target = Ember.lookup;
1690
+ if (hasThis) path = path.slice(5);
1694
1691
 
1695
- /**
1696
- @method has
1697
- @param obj
1698
- @return {Boolean}
1699
- */
1700
- has: function(obj) {
1701
- var guid = guidFor(obj),
1702
- presenceSet = this.presenceSet;
1692
+ if (target === Ember.lookup) {
1693
+ key = firstKey(path);
1694
+ target = get(target, key);
1695
+ path = path.slice(key.length+1);
1696
+ }
1703
1697
 
1704
- return guid in presenceSet;
1705
- },
1698
+ // must return some kind of path to be valid else other things will break.
1699
+ if (!path || path.length===0) throw new Error('Invalid Path');
1706
1700
 
1707
- /**
1708
- @method forEach
1709
- @param {Function} fn
1710
- @param self
1711
- */
1712
- forEach: function(fn, self) {
1713
- // allow mutation during iteration
1714
- var list = this.toArray();
1701
+ return [ target, path ];
1702
+ }
1715
1703
 
1716
- for (var i = 0, j = list.length; i < j; i++) {
1717
- fn.call(self, list[i]);
1718
- }
1719
- },
1704
+ var getPath = Ember._getPath = function(root, path) {
1705
+ var hasThis, parts, tuple, idx, len;
1720
1706
 
1721
- /**
1722
- @method toArray
1723
- @return {Array}
1724
- */
1725
- toArray: function() {
1726
- return this.list.slice();
1727
- },
1707
+ // If there is no root and path is a key name, return that
1708
+ // property from the global object.
1709
+ // E.g. get('Ember') -> Ember
1710
+ if (root === null && path.indexOf('.') === -1) { return get(Ember.lookup, path); }
1728
1711
 
1729
- /**
1730
- @method copy
1731
- @return {Ember.OrderedSet}
1732
- */
1733
- copy: function() {
1734
- var set = new OrderedSet();
1712
+ // detect complicated paths and normalize them
1713
+ hasThis = HAS_THIS.test(path);
1735
1714
 
1736
- set.presenceSet = copy(this.presenceSet);
1737
- set.list = this.toArray();
1715
+ if (!root || hasThis) {
1716
+ tuple = normalizeTuple(root, path);
1717
+ root = tuple[0];
1718
+ path = tuple[1];
1719
+ tuple.length = 0;
1720
+ }
1738
1721
 
1739
- return set;
1722
+ parts = path.split(".");
1723
+ len = parts.length;
1724
+ for (idx = 0; root != null && idx < len; idx++) {
1725
+ root = get(root, parts[idx], true);
1726
+ if (root && root.isDestroyed) { return undefined; }
1740
1727
  }
1728
+ return root;
1741
1729
  };
1742
1730
 
1743
1731
  /**
1744
- A Map stores values indexed by keys. Unlike JavaScript's
1745
- default Objects, the keys of a Map can be any JavaScript
1746
- object.
1747
-
1748
- Internally, a Map has two data structures:
1732
+ @private
1749
1733
 
1750
- 1. `keys`: an OrderedSet of all of the existing keys
1751
- 2. `values`: a JavaScript Object indexed by the `Ember.guidFor(key)`
1734
+ Normalizes a target/path pair to reflect that actual target/path that should
1735
+ be observed, etc. This takes into account passing in global property
1736
+ paths (i.e. a path beginning with a captial letter not defined on the
1737
+ target) and * separators.
1752
1738
 
1753
- When a key/value pair is added for the first time, we
1754
- add the key to the `keys` OrderedSet, and create or
1755
- replace an entry in `values`. When an entry is deleted,
1756
- we delete its entry in `keys` and `values`.
1757
-
1758
- @class Map
1759
- @namespace Ember
1760
- @private
1761
- @constructor
1739
+ @method normalizeTuple
1740
+ @for Ember
1741
+ @param {Object} target The current target. May be `null`.
1742
+ @param {String} path A path on the target or a global property path.
1743
+ @return {Array} a temporary array with the normalized target/path pair.
1762
1744
  */
1763
- var Map = Ember.Map = function() {
1764
- this.keys = Ember.OrderedSet.create();
1765
- this.values = {};
1745
+ Ember.normalizeTuple = function(target, path) {
1746
+ return normalizeTuple(target, path);
1766
1747
  };
1767
1748
 
1768
- /**
1769
- @method create
1770
- @static
1771
- */
1772
- Map.create = function() {
1773
- return new Map();
1749
+ Ember.getWithDefault = function(root, key, defaultValue) {
1750
+ var value = get(root, key);
1751
+
1752
+ if (value === undefined) { return defaultValue; }
1753
+ return value;
1774
1754
  };
1775
1755
 
1776
- Map.prototype = {
1777
- /**
1778
- Retrieve the value associated with a given key.
1779
1756
 
1780
- @method get
1781
- @param {*} key
1782
- @return {*} the value associated with the key, or `undefined`
1783
- */
1784
- get: function(key) {
1785
- var values = this.values,
1786
- guid = guidFor(key);
1757
+ Ember.get = get;
1758
+ Ember.getPath = Ember.deprecateFunc('getPath is deprecated since get now supports paths', Ember.get);
1787
1759
 
1788
- return values[guid];
1789
- },
1760
+ })();
1790
1761
 
1791
- /**
1792
- Adds a value to the map. If a value for the given key has already been
1793
- provided, the new value will replace the old value.
1794
1762
 
1795
- @method set
1796
- @param {*} key
1797
- @param {*} value
1798
- */
1799
- set: function(key, value) {
1800
- var keys = this.keys,
1801
- values = this.values,
1802
- guid = guidFor(key);
1803
1763
 
1804
- keys.add(key);
1805
- values[guid] = value;
1806
- },
1764
+ (function() {
1765
+ /**
1766
+ @module ember-metal
1767
+ */
1807
1768
 
1808
- /**
1809
- Removes a value from the map for an associated key.
1769
+ var o_create = Ember.create,
1770
+ metaFor = Ember.meta,
1771
+ META_KEY = Ember.META_KEY,
1772
+ /* listener flags */
1773
+ ONCE = 1, SUSPENDED = 2;
1810
1774
 
1811
- @method remove
1812
- @param {*} key
1813
- @return {Boolean} true if an item was removed, false otherwise
1814
- */
1815
- remove: function(key) {
1816
- // don't use ES6 "delete" because it will be annoying
1817
- // to use in browsers that are not ES6 friendly;
1818
- var keys = this.keys,
1819
- values = this.values,
1820
- guid = guidFor(key);
1775
+ /*
1776
+ The event system uses a series of nested hashes to store listeners on an
1777
+ object. When a listener is registered, or when an event arrives, these
1778
+ hashes are consulted to determine which target and action pair to invoke.
1821
1779
 
1822
- if (values.hasOwnProperty(guid)) {
1823
- keys.remove(key);
1824
- delete values[guid];
1825
- return true;
1826
- } else {
1827
- return false;
1828
- }
1829
- },
1780
+ The hashes are stored in the object's meta hash, and look like this:
1830
1781
 
1831
- /**
1832
- Check whether a key is present.
1782
+ // Object's meta hash
1783
+ {
1784
+ listeners: { // variable name: `listenerSet`
1785
+ "foo:changed": [ // variable name: `actions`
1786
+ [target, method, flags]
1787
+ ]
1788
+ }
1789
+ }
1833
1790
 
1834
- @method has
1835
- @param {*} key
1836
- @return {Boolean} true if the item was present, false otherwise
1837
- */
1838
- has: function(key) {
1839
- var values = this.values,
1840
- guid = guidFor(key);
1791
+ */
1841
1792
 
1842
- return values.hasOwnProperty(guid);
1843
- },
1793
+ function indexOf(array, target, method) {
1794
+ var index = -1;
1795
+ for (var i = 0, l = array.length; i < l; i++) {
1796
+ if (target === array[i][0] && method === array[i][1]) { index = i; break; }
1797
+ }
1798
+ return index;
1799
+ }
1844
1800
 
1845
- /**
1846
- Iterate over all the keys and values. Calls the function once
1847
- for each key, passing in the key and value, in that order.
1801
+ function actionsFor(obj, eventName) {
1802
+ var meta = metaFor(obj, true),
1803
+ actions;
1848
1804
 
1849
- The keys are guaranteed to be iterated over in insertion order.
1805
+ if (!meta.listeners) { meta.listeners = {}; }
1850
1806
 
1851
- @method forEach
1852
- @param {Function} callback
1853
- @param {*} self if passed, the `this` value inside the
1854
- callback. By default, `this` is the map.
1855
- */
1856
- forEach: function(callback, self) {
1857
- var keys = this.keys,
1858
- values = this.values;
1807
+ if (!meta.hasOwnProperty('listeners')) {
1808
+ // setup inherited copy of the listeners object
1809
+ meta.listeners = o_create(meta.listeners);
1810
+ }
1859
1811
 
1860
- keys.forEach(function(key) {
1861
- var guid = guidFor(key);
1862
- callback.call(self, key, values[guid]);
1863
- });
1864
- },
1812
+ actions = meta.listeners[eventName];
1865
1813
 
1866
- /**
1867
- @method copy
1868
- @return {Ember.Map}
1869
- */
1870
- copy: function() {
1871
- return copyMap(this, new Map());
1814
+ // if there are actions, but the eventName doesn't exist in our listeners, then copy them from the prototype
1815
+ if (actions && !meta.listeners.hasOwnProperty(eventName)) {
1816
+ actions = meta.listeners[eventName] = meta.listeners[eventName].slice();
1817
+ } else if (!actions) {
1818
+ actions = meta.listeners[eventName] = [];
1872
1819
  }
1873
- };
1874
1820
 
1875
- /**
1876
- @class MapWithDefault
1877
- @namespace Ember
1878
- @extends Ember.Map
1879
- @private
1880
- @constructor
1881
- @param [options]
1882
- @param {*} [options.defaultValue]
1883
- */
1884
- var MapWithDefault = Ember.MapWithDefault = function(options) {
1885
- Map.call(this);
1886
- this.defaultValue = options.defaultValue;
1887
- };
1821
+ return actions;
1822
+ }
1888
1823
 
1889
- /**
1890
- @method create
1891
- @static
1892
- @param [options]
1893
- @param {*} [options.defaultValue]
1894
- @return {Ember.MapWithDefault|Ember.Map} If options are passed, returns
1895
- `Ember.MapWithDefault` otherwise returns `Ember.Map`
1896
- */
1897
- MapWithDefault.create = function(options) {
1898
- if (options) {
1899
- return new MapWithDefault(options);
1900
- } else {
1901
- return new Map();
1824
+ function actionsUnion(obj, eventName, otherActions) {
1825
+ var meta = obj[META_KEY],
1826
+ actions = meta && meta.listeners && meta.listeners[eventName];
1827
+
1828
+ if (!actions) { return; }
1829
+ for (var i = actions.length - 1; i >= 0; i--) {
1830
+ var target = actions[i][0],
1831
+ method = actions[i][1],
1832
+ flags = actions[i][2],
1833
+ actionIndex = indexOf(otherActions, target, method);
1834
+
1835
+ if (actionIndex === -1) {
1836
+ otherActions.push([target, method, flags]);
1837
+ }
1902
1838
  }
1903
- };
1839
+ }
1904
1840
 
1905
- MapWithDefault.prototype = Ember.create(Map.prototype);
1841
+ function actionsDiff(obj, eventName, otherActions) {
1842
+ var meta = obj[META_KEY],
1843
+ actions = meta && meta.listeners && meta.listeners[eventName],
1844
+ diffActions = [];
1906
1845
 
1907
- /**
1908
- Retrieve the value associated with a given key.
1846
+ if (!actions) { return; }
1847
+ for (var i = actions.length - 1; i >= 0; i--) {
1848
+ var target = actions[i][0],
1849
+ method = actions[i][1],
1850
+ flags = actions[i][2],
1851
+ actionIndex = indexOf(otherActions, target, method);
1909
1852
 
1910
- @method get
1911
- @param {*} key
1912
- @return {*} the value associated with the key, or the default value
1913
- */
1914
- MapWithDefault.prototype.get = function(key) {
1915
- var hasValue = this.has(key);
1853
+ if (actionIndex !== -1) { continue; }
1916
1854
 
1917
- if (hasValue) {
1918
- return Map.prototype.get.call(this, key);
1919
- } else {
1920
- var defaultValue = this.defaultValue(key);
1921
- this.set(key, defaultValue);
1922
- return defaultValue;
1855
+ otherActions.push([target, method, flags]);
1856
+ diffActions.push([target, method, flags]);
1923
1857
  }
1924
- };
1858
+
1859
+ return diffActions;
1860
+ }
1925
1861
 
1926
1862
  /**
1927
- @method copy
1928
- @return {Ember.MapWithDefault}
1863
+ Add an event listener
1864
+
1865
+ @method addListener
1866
+ @for Ember
1867
+ @param obj
1868
+ @param {String} eventName
1869
+ @param {Object|Function} targetOrMethod A target object or a function
1870
+ @param {Function|String} method A function or the name of a function to be called on `target`
1871
+ @param {Boolean} once A flag whether a function should only be called once
1929
1872
  */
1930
- MapWithDefault.prototype.copy = function() {
1931
- return copyMap(this, new MapWithDefault({
1932
- defaultValue: this.defaultValue
1933
- }));
1934
- };
1873
+ function addListener(obj, eventName, target, method, once) {
1874
+ Ember.assert("You must pass at least an object and event name to Ember.addListener", !!obj && !!eventName);
1935
1875
 
1936
- })();
1876
+ if (!method && 'function' === typeof target) {
1877
+ method = target;
1878
+ target = null;
1879
+ }
1937
1880
 
1881
+ var actions = actionsFor(obj, eventName),
1882
+ actionIndex = indexOf(actions, target, method),
1883
+ flags = 0;
1938
1884
 
1885
+ if (once) flags |= ONCE;
1939
1886
 
1940
- (function() {
1941
- /**
1942
- @module ember-metal
1943
- */
1887
+ if (actionIndex !== -1) { return; }
1944
1888
 
1945
- var META_KEY = Ember.META_KEY, get;
1946
-
1947
- var MANDATORY_SETTER = Ember.ENV.MANDATORY_SETTER;
1948
-
1949
- var IS_GLOBAL_PATH = /^([A-Z$]|([0-9][A-Z$])).*[\.\*]/;
1950
- var HAS_THIS = /^this[\.\*]/;
1951
- var FIRST_KEY = /^([^\.\*]+)/;
1889
+ actions.push([target, method, flags]);
1952
1890
 
1953
- // ..........................................................
1954
- // GET AND SET
1955
- //
1956
- // If we are on a platform that supports accessors we can use those.
1957
- // Otherwise simulate accessors by looking up the property directly on the
1958
- // object.
1891
+ if ('function' === typeof obj.didAddListener) {
1892
+ obj.didAddListener(eventName, target, method);
1893
+ }
1894
+ }
1959
1895
 
1960
1896
  /**
1961
- Gets the value of a property on an object. If the property is computed,
1962
- the function will be invoked. If the property is not defined but the
1963
- object implements the `unknownProperty` method then that will be invoked.
1964
-
1965
- If you plan to run on IE8 and older browsers then you should use this
1966
- method anytime you want to retrieve a property on an object that you don't
1967
- know for sure is private. (Properties beginning with an underscore '_'
1968
- are considered private.)
1969
-
1970
- On all newer browsers, you only need to use this method to retrieve
1971
- properties if the property might not be defined on the object and you want
1972
- to respect the `unknownProperty` handler. Otherwise you can ignore this
1973
- method.
1897
+ Remove an event listener
1974
1898
 
1975
- Note that if the object itself is `undefined`, this method will throw
1976
- an error.
1899
+ Arguments should match those passed to `Ember.addListener`.
1977
1900
 
1978
- @method get
1901
+ @method removeListener
1979
1902
  @for Ember
1980
- @param {Object} obj The object to retrieve from.
1981
- @param {String} keyName The property key to retrieve
1982
- @return {Object} the property value or `null`.
1903
+ @param obj
1904
+ @param {String} eventName
1905
+ @param {Object|Function} targetOrMethod A target object or a function
1906
+ @param {Function|String} method A function or the name of a function to be called on `target`
1983
1907
  */
1984
- get = function get(obj, keyName) {
1985
- // Helpers that operate with 'this' within an #each
1986
- if (keyName === '') {
1987
- return obj;
1988
- }
1908
+ function removeListener(obj, eventName, target, method) {
1909
+ Ember.assert("You must pass at least an object and event name to Ember.removeListener", !!obj && !!eventName);
1989
1910
 
1990
- if (!keyName && 'string'===typeof obj) {
1991
- keyName = obj;
1992
- obj = null;
1911
+ if (!method && 'function' === typeof target) {
1912
+ method = target;
1913
+ target = null;
1993
1914
  }
1994
1915
 
1995
- if (!obj || keyName.indexOf('.') !== -1) {
1996
- Ember.assert("Cannot call get with '"+ keyName +"' on an undefined object.", obj !== undefined);
1997
- return getPath(obj, keyName);
1998
- }
1916
+ function _removeListener(target, method) {
1917
+ var actions = actionsFor(obj, eventName),
1918
+ actionIndex = indexOf(actions, target, method);
1999
1919
 
2000
- Ember.assert("You need to provide an object and key to `get`.", !!obj && keyName);
1920
+ // action doesn't exist, give up silently
1921
+ if (actionIndex === -1) { return; }
2001
1922
 
2002
- var meta = obj[META_KEY], desc = meta && meta.descs[keyName], ret;
2003
- if (desc) {
2004
- return desc.get(obj, keyName);
2005
- } else {
2006
- if (MANDATORY_SETTER && meta && meta.watching[keyName] > 0) {
2007
- ret = meta.values[keyName];
2008
- } else {
2009
- ret = obj[keyName];
2010
- }
1923
+ actions.splice(actionIndex, 1);
2011
1924
 
2012
- if (ret === undefined &&
2013
- 'object' === typeof obj && !(keyName in obj) && 'function' === typeof obj.unknownProperty) {
2014
- return obj.unknownProperty(keyName);
1925
+ if ('function' === typeof obj.didRemoveListener) {
1926
+ obj.didRemoveListener(eventName, target, method);
2015
1927
  }
2016
-
2017
- return ret;
2018
1928
  }
2019
- };
2020
-
2021
- // Currently used only by Ember Data tests
2022
- if (Ember.config.overrideAccessors) {
2023
- Ember.get = get;
2024
- Ember.config.overrideAccessors();
2025
- get = Ember.get;
2026
- }
2027
-
2028
- function firstKey(path) {
2029
- return path.match(FIRST_KEY)[0];
2030
- }
2031
-
2032
- // assumes path is already normalized
2033
- function normalizeTuple(target, path) {
2034
- var hasThis = HAS_THIS.test(path),
2035
- isGlobal = !hasThis && IS_GLOBAL_PATH.test(path),
2036
- key;
2037
1929
 
2038
- if (!target || isGlobal) target = Ember.lookup;
2039
- if (hasThis) path = path.slice(5);
1930
+ if (method) {
1931
+ _removeListener(target, method);
1932
+ } else {
1933
+ var meta = obj[META_KEY],
1934
+ actions = meta && meta.listeners && meta.listeners[eventName];
2040
1935
 
2041
- if (target === Ember.lookup) {
2042
- key = firstKey(path);
2043
- target = get(target, key);
2044
- path = path.slice(key.length+1);
1936
+ if (!actions) { return; }
1937
+ for (var i = actions.length - 1; i >= 0; i--) {
1938
+ _removeListener(actions[i][0], actions[i][1]);
1939
+ }
2045
1940
  }
2046
-
2047
- // must return some kind of path to be valid else other things will break.
2048
- if (!path || path.length===0) throw new Error('Invalid Path');
2049
-
2050
- return [ target, path ];
2051
1941
  }
2052
1942
 
2053
- var getPath = Ember._getPath = function(root, path) {
2054
- var hasThis, parts, tuple, idx, len;
1943
+ /**
1944
+ @private
2055
1945
 
2056
- // If there is no root and path is a key name, return that
2057
- // property from the global object.
2058
- // E.g. get('Ember') -> Ember
2059
- if (root === null && path.indexOf('.') === -1) { return get(Ember.lookup, path); }
1946
+ Suspend listener during callback.
2060
1947
 
2061
- // detect complicated paths and normalize them
2062
- hasThis = HAS_THIS.test(path);
1948
+ This should only be used by the target of the event listener
1949
+ when it is taking an action that would cause the event, e.g.
1950
+ an object might suspend its property change listener while it is
1951
+ setting that property.
2063
1952
 
2064
- if (!root || hasThis) {
2065
- tuple = normalizeTuple(root, path);
2066
- root = tuple[0];
2067
- path = tuple[1];
2068
- tuple.length = 0;
1953
+ @method suspendListener
1954
+ @for Ember
1955
+ @param obj
1956
+ @param {String} eventName
1957
+ @param {Object|Function} targetOrMethod A target object or a function
1958
+ @param {Function|String} method A function or the name of a function to be called on `target`
1959
+ @param {Function} callback
1960
+ */
1961
+ function suspendListener(obj, eventName, target, method, callback) {
1962
+ if (!method && 'function' === typeof target) {
1963
+ method = target;
1964
+ target = null;
2069
1965
  }
2070
1966
 
2071
- parts = path.split(".");
2072
- len = parts.length;
2073
- for (idx=0; root && idx<len; idx++) {
2074
- root = get(root, parts[idx], true);
2075
- if (root && root.isDestroyed) { return undefined; }
1967
+ var actions = actionsFor(obj, eventName),
1968
+ actionIndex = indexOf(actions, target, method),
1969
+ action;
1970
+
1971
+ if (actionIndex !== -1) {
1972
+ action = actions[actionIndex].slice(); // copy it, otherwise we're modifying a shared object
1973
+ action[2] |= SUSPENDED; // mark the action as suspended
1974
+ actions[actionIndex] = action; // replace the shared object with our copy
2076
1975
  }
2077
- return root;
2078
- };
1976
+
1977
+ function tryable() { return callback.call(target); }
1978
+ function finalizer() { if (action) { action[2] &= ~SUSPENDED; } }
1979
+
1980
+ return Ember.tryFinally(tryable, finalizer);
1981
+ }
2079
1982
 
2080
1983
  /**
2081
1984
  @private
2082
1985
 
2083
- Normalizes a target/path pair to reflect that actual target/path that should
2084
- be observed, etc. This takes into account passing in global property
2085
- paths (i.e. a path beginning with a captial letter not defined on the
2086
- target) and * separators.
1986
+ Suspend listener during callback.
2087
1987
 
2088
- @method normalizeTuple
1988
+ This should only be used by the target of the event listener
1989
+ when it is taking an action that would cause the event, e.g.
1990
+ an object might suspend its property change listener while it is
1991
+ setting that property.
1992
+
1993
+ @method suspendListener
2089
1994
  @for Ember
2090
- @param {Object} target The current target. May be `null`.
2091
- @param {String} path A path on the target or a global property path.
2092
- @return {Array} a temporary array with the normalized target/path pair.
1995
+ @param obj
1996
+ @param {Array} eventName Array of event names
1997
+ @param {Object|Function} targetOrMethod A target object or a function
1998
+ @param {Function|String} method A function or the name of a function to be called on `target`
1999
+ @param {Function} callback
2093
2000
  */
2094
- Ember.normalizeTuple = function(target, path) {
2095
- return normalizeTuple(target, path);
2096
- };
2001
+ function suspendListeners(obj, eventNames, target, method, callback) {
2002
+ if (!method && 'function' === typeof target) {
2003
+ method = target;
2004
+ target = null;
2005
+ }
2097
2006
 
2098
- Ember.getWithDefault = function(root, key, defaultValue) {
2099
- var value = get(root, key);
2007
+ var suspendedActions = [],
2008
+ eventName, actions, action, i, l;
2100
2009
 
2101
- if (value === undefined) { return defaultValue; }
2102
- return value;
2103
- };
2010
+ for (i=0, l=eventNames.length; i<l; i++) {
2011
+ eventName = eventNames[i];
2012
+ actions = actionsFor(obj, eventName);
2013
+ var actionIndex = indexOf(actions, target, method);
2104
2014
 
2015
+ if (actionIndex !== -1) {
2016
+ action = actions[actionIndex].slice();
2017
+ action[2] |= SUSPENDED;
2018
+ actions[actionIndex] = action;
2019
+ suspendedActions.push(action);
2020
+ }
2021
+ }
2105
2022
 
2106
- Ember.get = get;
2107
- Ember.getPath = Ember.deprecateFunc('getPath is deprecated since get now supports paths', Ember.get);
2108
- })();
2023
+ function tryable() { return callback.call(target); }
2109
2024
 
2025
+ function finalizer() {
2026
+ for (i = 0, l = suspendedActions.length; i < l; i++) {
2027
+ suspendedActions[i][2] &= ~SUSPENDED;
2028
+ }
2029
+ }
2110
2030
 
2031
+ return Ember.tryFinally(tryable, finalizer);
2032
+ }
2111
2033
 
2112
- (function() {
2113
2034
  /**
2114
- @module ember-metal
2115
- */
2116
-
2117
- var o_create = Ember.create,
2118
- metaFor = Ember.meta,
2119
- META_KEY = Ember.META_KEY;
2120
-
2121
- /*
2122
- The event system uses a series of nested hashes to store listeners on an
2123
- object. When a listener is registered, or when an event arrives, these
2124
- hashes are consulted to determine which target and action pair to invoke.
2125
-
2126
- The hashes are stored in the object's meta hash, and look like this:
2035
+ @private
2127
2036
 
2128
- // Object's meta hash
2129
- {
2130
- listeners: { // variable name: `listenerSet`
2131
- "foo:changed": [ // variable name: `actions`
2132
- [target, method, onceFlag, suspendedFlag]
2133
- ]
2134
- }
2135
- }
2037
+ Return a list of currently watched events
2136
2038
 
2039
+ @method watchedEvents
2040
+ @for Ember
2041
+ @param obj
2137
2042
  */
2138
-
2139
- function indexOf(array, target, method) {
2140
- var index = -1;
2141
- for (var i = 0, l = array.length; i < l; i++) {
2142
- if (target === array[i][0] && method === array[i][1]) { index = i; break; }
2143
- }
2144
- return index;
2145
- }
2146
-
2147
- function actionsFor(obj, eventName) {
2148
- var meta = metaFor(obj, true),
2149
- actions;
2150
-
2151
- if (!meta.listeners) { meta.listeners = {}; }
2152
-
2153
- if (!meta.hasOwnProperty('listeners')) {
2154
- // setup inherited copy of the listeners object
2155
- meta.listeners = o_create(meta.listeners);
2156
- }
2157
-
2158
- actions = meta.listeners[eventName];
2159
-
2160
- // if there are actions, but the eventName doesn't exist in our listeners, then copy them from the prototype
2161
- if (actions && !meta.listeners.hasOwnProperty(eventName)) {
2162
- actions = meta.listeners[eventName] = meta.listeners[eventName].slice();
2163
- } else if (!actions) {
2164
- actions = meta.listeners[eventName] = [];
2165
- }
2166
-
2167
- return actions;
2168
- }
2169
-
2170
- function actionsUnion(obj, eventName, otherActions) {
2171
- var meta = obj[META_KEY],
2172
- actions = meta && meta.listeners && meta.listeners[eventName];
2173
-
2174
- if (!actions) { return; }
2175
- for (var i = actions.length - 1; i >= 0; i--) {
2176
- var target = actions[i][0],
2177
- method = actions[i][1],
2178
- once = actions[i][2],
2179
- suspended = actions[i][3],
2180
- actionIndex = indexOf(otherActions, target, method);
2181
-
2182
- if (actionIndex === -1) {
2183
- otherActions.push([target, method, once, suspended]);
2184
- }
2185
- }
2186
- }
2187
-
2188
- function actionsDiff(obj, eventName, otherActions) {
2189
- var meta = obj[META_KEY],
2190
- actions = meta && meta.listeners && meta.listeners[eventName],
2191
- diffActions = [];
2192
-
2193
- if (!actions) { return; }
2194
- for (var i = actions.length - 1; i >= 0; i--) {
2195
- var target = actions[i][0],
2196
- method = actions[i][1],
2197
- once = actions[i][2],
2198
- suspended = actions[i][3],
2199
- actionIndex = indexOf(otherActions, target, method);
2200
-
2201
- if (actionIndex !== -1) { continue; }
2202
-
2203
- otherActions.push([target, method, once, suspended]);
2204
- diffActions.push([target, method, once, suspended]);
2205
- }
2206
-
2207
- return diffActions;
2208
- }
2209
-
2210
- /**
2211
- Add an event listener
2212
-
2213
- @method addListener
2214
- @for Ember
2215
- @param obj
2216
- @param {String} eventName
2217
- @param {Object|Function} targetOrMethod A target object or a function
2218
- @param {Function|String} method A function or the name of a function to be called on `target`
2219
- @param {Boolean} once A flag whether a function should only be called once
2220
- */
2221
- function addListener(obj, eventName, target, method, once) {
2222
- Ember.assert("You must pass at least an object and event name to Ember.addListener", !!obj && !!eventName);
2223
-
2224
- if (!method && 'function' === typeof target) {
2225
- method = target;
2226
- target = null;
2227
- }
2228
-
2229
- var actions = actionsFor(obj, eventName),
2230
- actionIndex = indexOf(actions, target, method);
2231
-
2232
- if (actionIndex !== -1) { return; }
2233
-
2234
- actions.push([target, method, once, undefined]);
2235
-
2236
- if ('function' === typeof obj.didAddListener) {
2237
- obj.didAddListener(eventName, target, method);
2238
- }
2239
- }
2240
-
2241
- /**
2242
- Remove an event listener
2243
-
2244
- Arguments should match those passed to {{#crossLink "Ember/addListener"}}{{/crossLink}}
2245
-
2246
- @method removeListener
2247
- @for Ember
2248
- @param obj
2249
- @param {String} eventName
2250
- @param {Object|Function} targetOrMethod A target object or a function
2251
- @param {Function|String} method A function or the name of a function to be called on `target`
2252
- */
2253
- function removeListener(obj, eventName, target, method) {
2254
- Ember.assert("You must pass at least an object and event name to Ember.removeListener", !!obj && !!eventName);
2255
-
2256
- if (!method && 'function' === typeof target) {
2257
- method = target;
2258
- target = null;
2259
- }
2260
-
2261
- function _removeListener(target, method, once) {
2262
- var actions = actionsFor(obj, eventName),
2263
- actionIndex = indexOf(actions, target, method);
2264
-
2265
- // action doesn't exist, give up silently
2266
- if (actionIndex === -1) { return; }
2267
-
2268
- actions.splice(actionIndex, 1);
2269
-
2270
- if ('function' === typeof obj.didRemoveListener) {
2271
- obj.didRemoveListener(eventName, target, method);
2272
- }
2273
- }
2274
-
2275
- if (method) {
2276
- _removeListener(target, method);
2277
- } else {
2278
- var meta = obj[META_KEY],
2279
- actions = meta && meta.listeners && meta.listeners[eventName];
2280
-
2281
- if (!actions) { return; }
2282
- for (var i = actions.length - 1; i >= 0; i--) {
2283
- _removeListener(actions[i][0], actions[i][1]);
2284
- }
2285
- }
2286
- }
2287
-
2288
- /**
2289
- @private
2290
-
2291
- Suspend listener during callback.
2292
-
2293
- This should only be used by the target of the event listener
2294
- when it is taking an action that would cause the event, e.g.
2295
- an object might suspend its property change listener while it is
2296
- setting that property.
2297
-
2298
- @method suspendListener
2299
- @for Ember
2300
- @param obj
2301
- @param {String} eventName
2302
- @param {Object|Function} targetOrMethod A target object or a function
2303
- @param {Function|String} method A function or the name of a function to be called on `target`
2304
- @param {Function} callback
2305
- */
2306
- function suspendListener(obj, eventName, target, method, callback) {
2307
- if (!method && 'function' === typeof target) {
2308
- method = target;
2309
- target = null;
2310
- }
2311
-
2312
- var actions = actionsFor(obj, eventName),
2313
- actionIndex = indexOf(actions, target, method),
2314
- action;
2315
-
2316
- if (actionIndex !== -1) {
2317
- action = actions[actionIndex].slice(); // copy it, otherwise we're modifying a shared object
2318
- action[3] = true; // mark the action as suspended
2319
- actions[actionIndex] = action; // replace the shared object with our copy
2320
- }
2321
-
2322
- function tryable() { return callback.call(target); }
2323
- function finalizer() { if (action) { action[3] = undefined; } }
2324
-
2325
- return Ember.tryFinally(tryable, finalizer);
2326
- }
2327
-
2328
- /**
2329
- @private
2330
-
2331
- Suspend listener during callback.
2332
-
2333
- This should only be used by the target of the event listener
2334
- when it is taking an action that would cause the event, e.g.
2335
- an object might suspend its property change listener while it is
2336
- setting that property.
2337
-
2338
- @method suspendListener
2339
- @for Ember
2340
- @param obj
2341
- @param {Array} eventName Array of event names
2342
- @param {Object|Function} targetOrMethod A target object or a function
2343
- @param {Function|String} method A function or the name of a function to be called on `target`
2344
- @param {Function} callback
2345
- */
2346
- function suspendListeners(obj, eventNames, target, method, callback) {
2347
- if (!method && 'function' === typeof target) {
2348
- method = target;
2349
- target = null;
2350
- }
2351
-
2352
- var suspendedActions = [],
2353
- eventName, actions, action, i, l;
2354
-
2355
- for (i=0, l=eventNames.length; i<l; i++) {
2356
- eventName = eventNames[i];
2357
- actions = actionsFor(obj, eventName);
2358
- var actionIndex = indexOf(actions, target, method);
2359
-
2360
- if (actionIndex !== -1) {
2361
- action = actions[actionIndex].slice();
2362
- action[3] = true;
2363
- actions[actionIndex] = action;
2364
- suspendedActions.push(action);
2365
- }
2366
- }
2367
-
2368
- function tryable() { return callback.call(target); }
2369
-
2370
- function finalizer() {
2371
- for (i = 0, l = suspendedActions.length; i < l; i++) {
2372
- suspendedActions[i][3] = undefined;
2373
- }
2374
- }
2375
-
2376
- return Ember.tryFinally(tryable, finalizer);
2377
- }
2378
-
2379
- /**
2380
- @private
2381
-
2382
- Return a list of currently watched events
2383
-
2384
- @method watchedEvents
2385
- @for Ember
2386
- @param obj
2387
- */
2388
- function watchedEvents(obj) {
2389
- var listeners = obj[META_KEY].listeners, ret = [];
2043
+ function watchedEvents(obj) {
2044
+ var listeners = obj[META_KEY].listeners, ret = [];
2390
2045
 
2391
2046
  if (listeners) {
2392
2047
  for(var eventName in listeners) {
@@ -2419,13 +2074,11 @@ function sendEvent(obj, eventName, params, actions) {
2419
2074
  if (!actions) { return; }
2420
2075
 
2421
2076
  for (var i = actions.length - 1; i >= 0; i--) { // looping in reverse for once listeners
2422
- if (!actions[i] || actions[i][3] === true) { continue; }
2423
-
2424
- var target = actions[i][0],
2425
- method = actions[i][1],
2426
- once = actions[i][2];
2427
-
2428
- if (once) { removeListener(obj, eventName, target, method); }
2077
+ var action = actions[i];
2078
+ if (!action) { continue; }
2079
+ var target = action[0], method = action[1], flags = action[2];
2080
+ if (flags & SUSPENDED) { continue; }
2081
+ if (flags & ONCE) { removeListener(obj, eventName, target, method); }
2429
2082
  if (!target) { target = obj; }
2430
2083
  if ('string' === typeof method) { method = target[method]; }
2431
2084
  if (params) {
@@ -2505,7 +2158,7 @@ var guidFor = Ember.guidFor,
2505
2158
  keyName: keyName,
2506
2159
  eventName: eventName,
2507
2160
  listeners: [
2508
- [target, method, onceFlag, suspendedFlag]
2161
+ [target, method, flags]
2509
2162
  ]
2510
2163
  },
2511
2164
  ...
@@ -2734,11 +2387,11 @@ var endPropertyChanges = Ember.endPropertyChanges = function() {
2734
2387
  });
2735
2388
  ```
2736
2389
 
2737
- @method changePropertiess
2390
+ @method changeProperties
2738
2391
  @param {Function} callback
2739
2392
  @param [binding]
2740
2393
  */
2741
- var changeProperties = Ember.changeProperties = function(cb, binding){
2394
+ Ember.changeProperties = function(cb, binding){
2742
2395
  beginPropertyChanges();
2743
2396
  tryFinally(cb, endPropertyChanges, binding);
2744
2397
  };
@@ -2852,66 +2505,446 @@ var set = function set(obj, keyName, value, tolerant) {
2852
2505
  Ember.propertyDidChange(obj, keyName);
2853
2506
  }
2854
2507
  } else {
2855
- obj[keyName] = value;
2508
+ obj[keyName] = value;
2509
+ }
2510
+ }
2511
+ return value;
2512
+ };
2513
+
2514
+ // Currently used only by Ember Data tests
2515
+ if (Ember.config.overrideAccessors) {
2516
+ Ember.set = set;
2517
+ Ember.config.overrideAccessors();
2518
+ set = Ember.set;
2519
+ }
2520
+
2521
+ function setPath(root, path, value, tolerant) {
2522
+ var keyName;
2523
+
2524
+ // get the last part of the path
2525
+ keyName = path.slice(path.lastIndexOf('.') + 1);
2526
+
2527
+ // get the first part of the part
2528
+ path = path.slice(0, path.length-(keyName.length+1));
2529
+
2530
+ // unless the path is this, look up the first part to
2531
+ // get the root
2532
+ if (path !== 'this') {
2533
+ root = getPath(root, path);
2534
+ }
2535
+
2536
+ if (!keyName || keyName.length === 0) {
2537
+ throw new Error('You passed an empty path');
2538
+ }
2539
+
2540
+ if (!root) {
2541
+ if (tolerant) { return; }
2542
+ else { throw new Error('Object in path '+path+' could not be found or was destroyed.'); }
2543
+ }
2544
+
2545
+ return set(root, keyName, value);
2546
+ }
2547
+
2548
+ Ember.set = set;
2549
+ Ember.setPath = Ember.deprecateFunc('setPath is deprecated since set now supports paths', Ember.set);
2550
+
2551
+ /**
2552
+ Error-tolerant form of `Ember.set`. Will not blow up if any part of the
2553
+ chain is `undefined`, `null`, or destroyed.
2554
+
2555
+ This is primarily used when syncing bindings, which may try to update after
2556
+ an object has been destroyed.
2557
+
2558
+ @method trySet
2559
+ @for Ember
2560
+ @param {Object} obj The object to modify.
2561
+ @param {String} path The property path to set
2562
+ @param {Object} value The value to set
2563
+ */
2564
+ Ember.trySet = function(root, path, value) {
2565
+ return set(root, path, value, true);
2566
+ };
2567
+ Ember.trySetPath = Ember.deprecateFunc('trySetPath has been renamed to trySet', Ember.trySet);
2568
+
2569
+ })();
2570
+
2571
+
2572
+
2573
+ (function() {
2574
+ /**
2575
+ @module ember-metal
2576
+ */
2577
+
2578
+ /*
2579
+ JavaScript (before ES6) does not have a Map implementation. Objects,
2580
+ which are often used as dictionaries, may only have Strings as keys.
2581
+
2582
+ Because Ember has a way to get a unique identifier for every object
2583
+ via `Ember.guidFor`, we can implement a performant Map with arbitrary
2584
+ keys. Because it is commonly used in low-level bookkeeping, Map is
2585
+ implemented as a pure JavaScript object for performance.
2586
+
2587
+ This implementation follows the current iteration of the ES6 proposal for
2588
+ maps (http://wiki.ecmascript.org/doku.php?id=harmony:simple_maps_and_sets),
2589
+ with two exceptions. First, because we need our implementation to be pleasant
2590
+ on older browsers, we do not use the `delete` name (using `remove` instead).
2591
+ Second, as we do not have the luxury of in-VM iteration, we implement a
2592
+ forEach method for iteration.
2593
+
2594
+ Map is mocked out to look like an Ember object, so you can do
2595
+ `Ember.Map.create()` for symmetry with other Ember classes.
2596
+ */
2597
+ var get = Ember.get,
2598
+ set = Ember.set,
2599
+ guidFor = Ember.guidFor,
2600
+ indexOf = Ember.ArrayPolyfills.indexOf;
2601
+
2602
+ var copy = function(obj) {
2603
+ var output = {};
2604
+
2605
+ for (var prop in obj) {
2606
+ if (obj.hasOwnProperty(prop)) { output[prop] = obj[prop]; }
2607
+ }
2608
+
2609
+ return output;
2610
+ };
2611
+
2612
+ var copyMap = function(original, newObject) {
2613
+ var keys = original.keys.copy(),
2614
+ values = copy(original.values);
2615
+
2616
+ newObject.keys = keys;
2617
+ newObject.values = values;
2618
+ newObject.length = original.length;
2619
+
2620
+ return newObject;
2621
+ };
2622
+
2623
+ /**
2624
+ This class is used internally by Ember and Ember Data.
2625
+ Please do not use it at this time. We plan to clean it up
2626
+ and add many tests soon.
2627
+
2628
+ @class OrderedSet
2629
+ @namespace Ember
2630
+ @constructor
2631
+ @private
2632
+ */
2633
+ var OrderedSet = Ember.OrderedSet = function() {
2634
+ this.clear();
2635
+ };
2636
+
2637
+ /**
2638
+ @method create
2639
+ @static
2640
+ @return {Ember.OrderedSet}
2641
+ */
2642
+ OrderedSet.create = function() {
2643
+ return new OrderedSet();
2644
+ };
2645
+
2646
+
2647
+ OrderedSet.prototype = {
2648
+ /**
2649
+ @method clear
2650
+ */
2651
+ clear: function() {
2652
+ this.presenceSet = {};
2653
+ this.list = [];
2654
+ },
2655
+
2656
+ /**
2657
+ @method add
2658
+ @param obj
2659
+ */
2660
+ add: function(obj) {
2661
+ var guid = guidFor(obj),
2662
+ presenceSet = this.presenceSet,
2663
+ list = this.list;
2664
+
2665
+ if (guid in presenceSet) { return; }
2666
+
2667
+ presenceSet[guid] = true;
2668
+ list.push(obj);
2669
+ },
2670
+
2671
+ /**
2672
+ @method remove
2673
+ @param obj
2674
+ */
2675
+ remove: function(obj) {
2676
+ var guid = guidFor(obj),
2677
+ presenceSet = this.presenceSet,
2678
+ list = this.list;
2679
+
2680
+ delete presenceSet[guid];
2681
+
2682
+ var index = indexOf.call(list, obj);
2683
+ if (index > -1) {
2684
+ list.splice(index, 1);
2685
+ }
2686
+ },
2687
+
2688
+ /**
2689
+ @method isEmpty
2690
+ @return {Boolean}
2691
+ */
2692
+ isEmpty: function() {
2693
+ return this.list.length === 0;
2694
+ },
2695
+
2696
+ /**
2697
+ @method has
2698
+ @param obj
2699
+ @return {Boolean}
2700
+ */
2701
+ has: function(obj) {
2702
+ var guid = guidFor(obj),
2703
+ presenceSet = this.presenceSet;
2704
+
2705
+ return guid in presenceSet;
2706
+ },
2707
+
2708
+ /**
2709
+ @method forEach
2710
+ @param {Function} fn
2711
+ @param self
2712
+ */
2713
+ forEach: function(fn, self) {
2714
+ // allow mutation during iteration
2715
+ var list = this.toArray();
2716
+
2717
+ for (var i = 0, j = list.length; i < j; i++) {
2718
+ fn.call(self, list[i]);
2719
+ }
2720
+ },
2721
+
2722
+ /**
2723
+ @method toArray
2724
+ @return {Array}
2725
+ */
2726
+ toArray: function() {
2727
+ return this.list.slice();
2728
+ },
2729
+
2730
+ /**
2731
+ @method copy
2732
+ @return {Ember.OrderedSet}
2733
+ */
2734
+ copy: function() {
2735
+ var set = new OrderedSet();
2736
+
2737
+ set.presenceSet = copy(this.presenceSet);
2738
+ set.list = this.toArray();
2739
+
2740
+ return set;
2741
+ }
2742
+ };
2743
+
2744
+ /**
2745
+ A Map stores values indexed by keys. Unlike JavaScript's
2746
+ default Objects, the keys of a Map can be any JavaScript
2747
+ object.
2748
+
2749
+ Internally, a Map has two data structures:
2750
+
2751
+ 1. `keys`: an OrderedSet of all of the existing keys
2752
+ 2. `values`: a JavaScript Object indexed by the `Ember.guidFor(key)`
2753
+
2754
+ When a key/value pair is added for the first time, we
2755
+ add the key to the `keys` OrderedSet, and create or
2756
+ replace an entry in `values`. When an entry is deleted,
2757
+ we delete its entry in `keys` and `values`.
2758
+
2759
+ @class Map
2760
+ @namespace Ember
2761
+ @private
2762
+ @constructor
2763
+ */
2764
+ var Map = Ember.Map = function() {
2765
+ this.keys = Ember.OrderedSet.create();
2766
+ this.values = {};
2767
+ };
2768
+
2769
+ /**
2770
+ @method create
2771
+ @static
2772
+ */
2773
+ Map.create = function() {
2774
+ return new Map();
2775
+ };
2776
+
2777
+ Map.prototype = {
2778
+ /**
2779
+ This property will change as the number of objects in the map changes.
2780
+
2781
+ @property length
2782
+ @type number
2783
+ @default 0
2784
+ */
2785
+ length: 0,
2786
+
2787
+
2788
+ /**
2789
+ Retrieve the value associated with a given key.
2790
+
2791
+ @method get
2792
+ @param {*} key
2793
+ @return {*} the value associated with the key, or `undefined`
2794
+ */
2795
+ get: function(key) {
2796
+ var values = this.values,
2797
+ guid = guidFor(key);
2798
+
2799
+ return values[guid];
2800
+ },
2801
+
2802
+ /**
2803
+ Adds a value to the map. If a value for the given key has already been
2804
+ provided, the new value will replace the old value.
2805
+
2806
+ @method set
2807
+ @param {*} key
2808
+ @param {*} value
2809
+ */
2810
+ set: function(key, value) {
2811
+ var keys = this.keys,
2812
+ values = this.values,
2813
+ guid = guidFor(key);
2814
+
2815
+ keys.add(key);
2816
+ values[guid] = value;
2817
+ set(this, 'length', keys.list.length);
2818
+ },
2819
+
2820
+ /**
2821
+ Removes a value from the map for an associated key.
2822
+
2823
+ @method remove
2824
+ @param {*} key
2825
+ @return {Boolean} true if an item was removed, false otherwise
2826
+ */
2827
+ remove: function(key) {
2828
+ // don't use ES6 "delete" because it will be annoying
2829
+ // to use in browsers that are not ES6 friendly;
2830
+ var keys = this.keys,
2831
+ values = this.values,
2832
+ guid = guidFor(key);
2833
+
2834
+ if (values.hasOwnProperty(guid)) {
2835
+ keys.remove(key);
2836
+ delete values[guid];
2837
+ set(this, 'length', keys.list.length);
2838
+ return true;
2839
+ } else {
2840
+ return false;
2856
2841
  }
2857
- }
2858
- return value;
2859
- };
2842
+ },
2860
2843
 
2861
- // Currently used only by Ember Data tests
2862
- if (Ember.config.overrideAccessors) {
2863
- Ember.set = set;
2864
- Ember.config.overrideAccessors();
2865
- set = Ember.set;
2866
- }
2844
+ /**
2845
+ Check whether a key is present.
2867
2846
 
2868
- function setPath(root, path, value, tolerant) {
2869
- var keyName;
2847
+ @method has
2848
+ @param {*} key
2849
+ @return {Boolean} true if the item was present, false otherwise
2850
+ */
2851
+ has: function(key) {
2852
+ var values = this.values,
2853
+ guid = guidFor(key);
2870
2854
 
2871
- // get the last part of the path
2872
- keyName = path.slice(path.lastIndexOf('.') + 1);
2855
+ return values.hasOwnProperty(guid);
2856
+ },
2873
2857
 
2874
- // get the first part of the part
2875
- path = path.slice(0, path.length-(keyName.length+1));
2858
+ /**
2859
+ Iterate over all the keys and values. Calls the function once
2860
+ for each key, passing in the key and value, in that order.
2876
2861
 
2877
- // unless the path is this, look up the first part to
2878
- // get the root
2879
- if (path !== 'this') {
2880
- root = getPath(root, path);
2881
- }
2862
+ The keys are guaranteed to be iterated over in insertion order.
2882
2863
 
2883
- if (!keyName || keyName.length === 0) {
2884
- throw new Error('You passed an empty path');
2885
- }
2864
+ @method forEach
2865
+ @param {Function} callback
2866
+ @param {*} self if passed, the `this` value inside the
2867
+ callback. By default, `this` is the map.
2868
+ */
2869
+ forEach: function(callback, self) {
2870
+ var keys = this.keys,
2871
+ values = this.values;
2886
2872
 
2887
- if (!root) {
2888
- if (tolerant) { return; }
2889
- else { throw new Error('Object in path '+path+' could not be found or was destroyed.'); }
2873
+ keys.forEach(function(key) {
2874
+ var guid = guidFor(key);
2875
+ callback.call(self, key, values[guid]);
2876
+ });
2877
+ },
2878
+
2879
+ /**
2880
+ @method copy
2881
+ @return {Ember.Map}
2882
+ */
2883
+ copy: function() {
2884
+ return copyMap(this, new Map());
2890
2885
  }
2886
+ };
2891
2887
 
2892
- return set(root, keyName, value);
2893
- }
2888
+ /**
2889
+ @class MapWithDefault
2890
+ @namespace Ember
2891
+ @extends Ember.Map
2892
+ @private
2893
+ @constructor
2894
+ @param [options]
2895
+ @param {*} [options.defaultValue]
2896
+ */
2897
+ var MapWithDefault = Ember.MapWithDefault = function(options) {
2898
+ Map.call(this);
2899
+ this.defaultValue = options.defaultValue;
2900
+ };
2894
2901
 
2895
- Ember.set = set;
2896
- Ember.setPath = Ember.deprecateFunc('setPath is deprecated since set now supports paths', Ember.set);
2902
+ /**
2903
+ @method create
2904
+ @static
2905
+ @param [options]
2906
+ @param {*} [options.defaultValue]
2907
+ @return {Ember.MapWithDefault|Ember.Map} If options are passed, returns
2908
+ `Ember.MapWithDefault` otherwise returns `Ember.Map`
2909
+ */
2910
+ MapWithDefault.create = function(options) {
2911
+ if (options) {
2912
+ return new MapWithDefault(options);
2913
+ } else {
2914
+ return new Map();
2915
+ }
2916
+ };
2917
+
2918
+ MapWithDefault.prototype = Ember.create(Map.prototype);
2897
2919
 
2898
2920
  /**
2899
- Error-tolerant form of `Ember.set`. Will not blow up if any part of the
2900
- chain is `undefined`, `null`, or destroyed.
2921
+ Retrieve the value associated with a given key.
2901
2922
 
2902
- This is primarily used when syncing bindings, which may try to update after
2903
- an object has been destroyed.
2923
+ @method get
2924
+ @param {*} key
2925
+ @return {*} the value associated with the key, or the default value
2926
+ */
2927
+ MapWithDefault.prototype.get = function(key) {
2928
+ var hasValue = this.has(key);
2904
2929
 
2905
- @method trySet
2906
- @for Ember
2907
- @param {Object} obj The object to modify.
2908
- @param {String} path The property path to set
2909
- @param {Object} value The value to set
2930
+ if (hasValue) {
2931
+ return Map.prototype.get.call(this, key);
2932
+ } else {
2933
+ var defaultValue = this.defaultValue(key);
2934
+ this.set(key, defaultValue);
2935
+ return defaultValue;
2936
+ }
2937
+ };
2938
+
2939
+ /**
2940
+ @method copy
2941
+ @return {Ember.MapWithDefault}
2910
2942
  */
2911
- Ember.trySet = function(root, path, value) {
2912
- return set(root, path, value, true);
2943
+ MapWithDefault.prototype.copy = function() {
2944
+ return copyMap(this, new MapWithDefault({
2945
+ defaultValue: this.defaultValue
2946
+ }));
2913
2947
  };
2914
- Ember.trySetPath = Ember.deprecateFunc('trySetPath has been renamed to trySet', Ember.trySet);
2915
2948
 
2916
2949
  })();
2917
2950
 
@@ -2943,7 +2976,7 @@ var MANDATORY_SETTER = Ember.ENV.MANDATORY_SETTER;
2943
2976
  @private
2944
2977
  @constructor
2945
2978
  */
2946
- var Descriptor = Ember.Descriptor = function() {};
2979
+ Ember.Descriptor = function() {};
2947
2980
 
2948
2981
  // ..........................................................
2949
2982
  // DEFINING PROPERTIES API
@@ -3504,7 +3537,7 @@ Ember.watchPath = function(obj, keyPath) {
3504
3537
  };
3505
3538
 
3506
3539
  Ember.unwatchPath = function(obj, keyPath) {
3507
- var m = metaFor(obj), watching = m.watching, desc;
3540
+ var m = metaFor(obj), watching = m.watching;
3508
3541
 
3509
3542
  if (watching[keyPath] === 1) {
3510
3543
  watching[keyPath] = 0;
@@ -3766,27 +3799,14 @@ ComputedProperty.prototype = new Ember.Descriptor();
3766
3799
  var ComputedPropertyPrototype = ComputedProperty.prototype;
3767
3800
 
3768
3801
  /*
3769
- Call on a computed property to explicitly change it's cacheable mode.
3770
-
3771
- Please use `.volatile` over this method.
3772
-
3773
- ```javascript
3774
- MyApp.president = Ember.Object.create({
3775
- fullName: function() {
3776
- return this.get('firstName') + ' ' + this.get('lastName');
3777
-
3778
- // By default, Ember will return the value of this property
3779
- // without re-executing this function.
3780
- }.property('firstName', 'lastName')
3802
+ Properties are cacheable by default. Computed property will automatically
3803
+ cache the return value of your function until one of the dependent keys changes.
3781
3804
 
3782
- initials: function() {
3783
- return this.get('firstName')[0] + this.get('lastName')[0];
3805
+ Call `volatile()` to set it into non-cached mode. When in this mode
3806
+ the computed property will not automatically cache the return value.
3784
3807
 
3785
- // This function will be executed every time this property
3786
- // is requested.
3787
- }.property('firstName', 'lastName').cacheable(false)
3788
- });
3789
- ```
3808
+ However, if a property is properly observable, there is no reason to disable
3809
+ caching.
3790
3810
 
3791
3811
  @method cacheable
3792
3812
  @param {Boolean} aFlag optional set to `false` to disable caching
@@ -4050,7 +4070,6 @@ ComputedPropertyPrototype.teardown = function(obj, keyName) {
4050
4070
  The function should accept two parameters, key and value. If value is not
4051
4071
  undefined you should set the value first. In either case return the
4052
4072
  current value of the property.
4053
-
4054
4073
  @method computed
4055
4074
  @for Ember
4056
4075
  @param {Function} func The computed property function.
@@ -4292,7 +4311,7 @@ registerComputedWithProperties('or', function(properties) {
4292
4311
  @for Ember
4293
4312
  @param {String} dependentKey, [dependentKey...]
4294
4313
  @return {Ember.ComputedProperty} computed property which returns
4295
- the first trouthy value of given list of properties.
4314
+ the first truthy value of given list of properties.
4296
4315
  */
4297
4316
  registerComputedWithProperties('any', function(properties) {
4298
4317
  for (var key in properties) {
@@ -4342,6 +4361,48 @@ Ember.computed.alias = function(dependentKey) {
4342
4361
  });
4343
4362
  };
4344
4363
 
4364
+ /**
4365
+ @method computed.oneWay
4366
+ @for Ember
4367
+ @param {String} dependentKey
4368
+ @return {Ember.ComputedProperty} computed property which creates an
4369
+ one way computed property to the original value for property.
4370
+
4371
+ Where `computed.alias` aliases `get` and `set`, and allows for bidirectional
4372
+ data flow, `computed.oneWay` only provides an aliased `get`. The `set` will
4373
+ not mutate the upstream property, rather causes the current property to
4374
+ become the value set. This causes the downstream property to permentantly
4375
+ diverge from the upstream property.
4376
+
4377
+ ```javascript
4378
+ User = Ember.Object.extend({
4379
+ firstName: null,
4380
+ lastName: null,
4381
+ nickName: Ember.computed.oneWay('firstName')
4382
+ });
4383
+
4384
+ user = User.create({
4385
+ firstName: 'Teddy',
4386
+ lastName: 'Zeenny'
4387
+ });
4388
+
4389
+ user.get('nickName');
4390
+ # 'Teddy'
4391
+
4392
+ user.set('nickName', 'TeddyBear');
4393
+ # 'TeddyBear'
4394
+
4395
+ user.get('firstName');
4396
+ # 'Teddy'
4397
+ ```
4398
+ */
4399
+ Ember.computed.oneWay = function(dependentKey) {
4400
+ return Ember.computed(dependentKey, function() {
4401
+ return get(this, dependentKey);
4402
+ });
4403
+ };
4404
+
4405
+
4345
4406
  /**
4346
4407
  @method computed.defaultTo
4347
4408
  @for Ember
@@ -4371,8 +4432,6 @@ Ember.computed.defaultTo = function(defaultPath) {
4371
4432
  var AFTER_OBSERVERS = ':change';
4372
4433
  var BEFORE_OBSERVERS = ':before';
4373
4434
 
4374
- var guidFor = Ember.guidFor;
4375
-
4376
4435
  function changeEvent(keyName) {
4377
4436
  return keyName+AFTER_OBSERVERS;
4378
4437
  }
@@ -4432,220 +4491,544 @@ Ember._suspendBeforeObserver = function(obj, path, target, method, callback) {
4432
4491
  return Ember._suspendListener(obj, beforeEvent(path), target, method, callback);
4433
4492
  };
4434
4493
 
4435
- Ember._suspendObserver = function(obj, path, target, method, callback) {
4436
- return Ember._suspendListener(obj, changeEvent(path), target, method, callback);
4437
- };
4494
+ Ember._suspendObserver = function(obj, path, target, method, callback) {
4495
+ return Ember._suspendListener(obj, changeEvent(path), target, method, callback);
4496
+ };
4497
+
4498
+ var map = Ember.ArrayPolyfills.map;
4499
+
4500
+ Ember._suspendBeforeObservers = function(obj, paths, target, method, callback) {
4501
+ var events = map.call(paths, beforeEvent);
4502
+ return Ember._suspendListeners(obj, events, target, method, callback);
4503
+ };
4504
+
4505
+ Ember._suspendObservers = function(obj, paths, target, method, callback) {
4506
+ var events = map.call(paths, changeEvent);
4507
+ return Ember._suspendListeners(obj, events, target, method, callback);
4508
+ };
4509
+
4510
+ Ember.beforeObserversFor = function(obj, path) {
4511
+ return Ember.listenersFor(obj, beforeEvent(path));
4512
+ };
4513
+
4514
+ /**
4515
+ @method removeBeforeObserver
4516
+ @param obj
4517
+ @param {String} path
4518
+ @param {Object|Function} targetOrMethod
4519
+ @param {Function|String} [method]
4520
+ */
4521
+ Ember.removeBeforeObserver = function(obj, path, target, method) {
4522
+ Ember.unwatch(obj, path);
4523
+ Ember.removeListener(obj, beforeEvent(path), target, method);
4524
+ return this;
4525
+ };
4526
+ })();
4527
+
4528
+
4529
+
4530
+ (function() {
4531
+ define("backburner",
4532
+ ["backburner/deferred_action_queues","exports"],
4533
+ function(__dependency1__, __exports__) {
4534
+ "use strict";
4535
+ var DeferredActionQueues = __dependency1__.DeferredActionQueues;
4536
+
4537
+ var slice = [].slice,
4538
+ pop = [].pop,
4539
+ debouncees = [],
4540
+ timers = [],
4541
+ autorun, laterTimer, laterTimerExpiresAt;
4542
+
4543
+ function Backburner(queueNames, options) {
4544
+ this.queueNames = queueNames;
4545
+ this.options = options || {};
4546
+ if (!this.options.defaultQueue) {
4547
+ this.options.defaultQueue = queueNames[0];
4548
+ }
4549
+ this.instanceStack = [];
4550
+ }
4551
+
4552
+ Backburner.prototype = {
4553
+ queueNames: null,
4554
+ options: null,
4555
+ currentInstance: null,
4556
+ instanceStack: null,
4557
+
4558
+ begin: function() {
4559
+ var onBegin = this.options && this.options.onBegin,
4560
+ previousInstance = this.currentInstance;
4561
+
4562
+ if (previousInstance) {
4563
+ this.instanceStack.push(previousInstance);
4564
+ }
4565
+
4566
+ this.currentInstance = new DeferredActionQueues(this.queueNames, this.options);
4567
+ if (onBegin) {
4568
+ onBegin(this.currentInstance, previousInstance);
4569
+ }
4570
+ },
4571
+
4572
+ end: function() {
4573
+ var onEnd = this.options && this.options.onEnd,
4574
+ currentInstance = this.currentInstance,
4575
+ nextInstance = null;
4576
+
4577
+ try {
4578
+ currentInstance.flush();
4579
+ } finally {
4580
+ this.currentInstance = null;
4581
+
4582
+ if (this.instanceStack.length) {
4583
+ nextInstance = this.instanceStack.pop();
4584
+ this.currentInstance = nextInstance;
4585
+ }
4586
+
4587
+ if (onEnd) {
4588
+ onEnd(currentInstance, nextInstance);
4589
+ }
4590
+ }
4591
+ },
4592
+
4593
+ run: function(target, method /*, args */) {
4594
+ var ret;
4595
+ this.begin();
4596
+
4597
+ if (!method) {
4598
+ method = target;
4599
+ target = null;
4600
+ }
4601
+
4602
+ if (typeof method === 'string') {
4603
+ method = target[method];
4604
+ }
4605
+
4606
+ // Prevent Safari double-finally.
4607
+ var finallyAlreadyCalled = false;
4608
+ try {
4609
+ if (arguments.length > 2) {
4610
+ ret = method.apply(target, slice.call(arguments, 2));
4611
+ } else {
4612
+ ret = method.call(target);
4613
+ }
4614
+ } finally {
4615
+ if (!finallyAlreadyCalled) {
4616
+ finallyAlreadyCalled = true;
4617
+ this.end();
4618
+ }
4619
+ }
4620
+ return ret;
4621
+ },
4438
4622
 
4439
- var map = Ember.ArrayPolyfills.map;
4623
+ defer: function(queueName, target, method /* , args */) {
4624
+ if (!method) {
4625
+ method = target;
4626
+ target = null;
4627
+ }
4440
4628
 
4441
- Ember._suspendBeforeObservers = function(obj, paths, target, method, callback) {
4442
- var events = map.call(paths, beforeEvent);
4443
- return Ember._suspendListeners(obj, events, target, method, callback);
4444
- };
4629
+ if (typeof method === 'string') {
4630
+ method = target[method];
4631
+ }
4445
4632
 
4446
- Ember._suspendObservers = function(obj, paths, target, method, callback) {
4447
- var events = map.call(paths, changeEvent);
4448
- return Ember._suspendListeners(obj, events, target, method, callback);
4449
- };
4633
+ var stack = new Error().stack,
4634
+ args = arguments.length > 3 ? slice.call(arguments, 3) : undefined;
4635
+ if (!this.currentInstance) { createAutorun(this); }
4636
+ return this.currentInstance.schedule(queueName, target, method, args, false, stack);
4637
+ },
4450
4638
 
4451
- Ember.beforeObserversFor = function(obj, path) {
4452
- return Ember.listenersFor(obj, beforeEvent(path));
4453
- };
4639
+ deferOnce: function(queueName, target, method /* , args */) {
4640
+ if (!method) {
4641
+ method = target;
4642
+ target = null;
4643
+ }
4454
4644
 
4455
- /**
4456
- @method removeBeforeObserver
4457
- @param obj
4458
- @param {String} path
4459
- @param {Object|Function} targetOrMethod
4460
- @param {Function|String} [method]
4461
- */
4462
- Ember.removeBeforeObserver = function(obj, path, target, method) {
4463
- Ember.unwatch(obj, path);
4464
- Ember.removeListener(obj, beforeEvent(path), target, method);
4465
- return this;
4466
- };
4467
- })();
4645
+ if (typeof method === 'string') {
4646
+ method = target[method];
4647
+ }
4468
4648
 
4649
+ var stack = new Error().stack,
4650
+ args = arguments.length > 3 ? slice.call(arguments, 3) : undefined;
4651
+ if (!this.currentInstance) { createAutorun(this); }
4652
+ return this.currentInstance.schedule(queueName, target, method, args, true, stack);
4653
+ },
4469
4654
 
4655
+ setTimeout: function() {
4656
+ var self = this,
4657
+ wait = pop.call(arguments),
4658
+ target = arguments[0],
4659
+ method = arguments[1],
4660
+ executeAt = (+new Date()) + wait;
4470
4661
 
4471
- (function() {
4472
- // Ember.Logger
4473
- // Ember.watch.flushPending
4474
- // Ember.beginPropertyChanges, Ember.endPropertyChanges
4475
- // Ember.guidFor, Ember.tryFinally
4662
+ if (!method) {
4663
+ method = target;
4664
+ target = null;
4665
+ }
4476
4666
 
4477
- /**
4478
- @module ember-metal
4479
- */
4667
+ if (typeof method === 'string') {
4668
+ method = target[method];
4669
+ }
4480
4670
 
4481
- // ..........................................................
4482
- // HELPERS
4483
- //
4671
+ var fn, args;
4672
+ if (arguments.length > 2) {
4673
+ args = slice.call(arguments, 2);
4484
4674
 
4485
- var slice = [].slice,
4486
- forEach = Ember.ArrayPolyfills.forEach;
4675
+ fn = function() {
4676
+ method.apply(target, args);
4677
+ };
4678
+ } else {
4679
+ fn = function() {
4680
+ method.call(target);
4681
+ };
4682
+ }
4487
4683
 
4488
- // invokes passed params - normalizing so you can pass target/func,
4489
- // target/string or just func
4490
- function invoke(target, method, args, ignore) {
4684
+ // find position to insert - TODO: binary search
4685
+ var i, l;
4686
+ for (i = 0, l = timers.length; i < l; i += 2) {
4687
+ if (executeAt < timers[i]) { break; }
4688
+ }
4491
4689
 
4492
- if (method === undefined) {
4493
- method = target;
4494
- target = undefined;
4495
- }
4690
+ timers.splice(i, 0, executeAt, fn);
4496
4691
 
4497
- if ('string' === typeof method) { method = target[method]; }
4498
- if (args && ignore > 0) {
4499
- args = args.length > ignore ? slice.call(args, ignore) : null;
4500
- }
4692
+ if (laterTimer && laterTimerExpiresAt < executeAt) { return fn; }
4501
4693
 
4502
- return Ember.handleErrors(function() {
4503
- // IE8's Function.prototype.apply doesn't accept undefined/null arguments.
4504
- return method.apply(target || this, args || []);
4505
- }, this);
4506
- }
4694
+ if (laterTimer) {
4695
+ clearTimeout(laterTimer);
4696
+ laterTimer = null;
4697
+ }
4698
+ laterTimer = setTimeout(function() {
4699
+ executeTimers(self);
4700
+ laterTimer = null;
4701
+ laterTimerExpiresAt = null;
4702
+ }, wait);
4703
+ laterTimerExpiresAt = executeAt;
4704
+
4705
+ return fn;
4706
+ },
4507
4707
 
4708
+ debounce: function(target, method /* , args, wait */) {
4709
+ var self = this,
4710
+ args = arguments,
4711
+ wait = pop.call(args),
4712
+ debouncee;
4508
4713
 
4509
- // ..........................................................
4510
- // RUNLOOP
4511
- //
4714
+ for (var i = 0, l = debouncees.length; i < l; i++) {
4715
+ debouncee = debouncees[i];
4716
+ if (debouncee[0] === target && debouncee[1] === method) { return; } // do nothing
4717
+ }
4512
4718
 
4513
- /**
4514
- Ember RunLoop (Private)
4719
+ var timer = setTimeout(function() {
4720
+ self.run.apply(self, args);
4515
4721
 
4516
- @class RunLoop
4517
- @namespace Ember
4518
- @private
4519
- @constructor
4520
- */
4521
- var RunLoop = function(prev) {
4522
- this._prev = prev || null;
4523
- this.onceTimers = {};
4524
- };
4722
+ // remove debouncee
4723
+ var index = -1;
4724
+ for (var i = 0, l = debouncees.length; i < l; i++) {
4725
+ debouncee = debouncees[i];
4726
+ if (debouncee[0] === target && debouncee[1] === method) {
4727
+ index = i;
4728
+ break;
4729
+ }
4730
+ }
4525
4731
 
4526
- RunLoop.prototype = {
4527
- /**
4528
- @method end
4529
- */
4530
- end: function() {
4531
- this.flush();
4532
- },
4732
+ if (index > -1) { debouncees.splice(index, 1); }
4733
+ }, wait);
4533
4734
 
4534
- /**
4535
- @method prev
4536
- */
4537
- prev: function() {
4538
- return this._prev;
4539
- },
4735
+ debouncees.push([target, method, timer]);
4736
+ },
4540
4737
 
4541
- // ..........................................................
4542
- // Delayed Actions
4543
- //
4738
+ cancelTimers: function() {
4739
+ for (var i = 0, l = debouncees.length; i < l; i++) {
4740
+ clearTimeout(debouncees[i][2]);
4741
+ }
4742
+ debouncees = [];
4544
4743
 
4545
- /**
4546
- @method schedule
4547
- @param {String} queueName
4548
- @param target
4549
- @param method
4550
- */
4551
- schedule: function(queueName, target, method) {
4552
- var queues = this._queues, queue;
4553
- if (!queues) { queues = this._queues = {}; }
4554
- queue = queues[queueName];
4555
- if (!queue) { queue = queues[queueName] = []; }
4744
+ if (laterTimer) {
4745
+ clearTimeout(laterTimer);
4746
+ laterTimer = null;
4747
+ }
4748
+ timers = [];
4556
4749
 
4557
- var args = arguments.length > 3 ? slice.call(arguments, 3) : null;
4558
- queue.push({ target: target, method: method, args: args });
4559
- return this;
4560
- },
4750
+ if (autorun) {
4751
+ clearTimeout(autorun);
4752
+ autorun = null;
4753
+ }
4754
+ },
4561
4755
 
4562
- /**
4563
- @method flush
4564
- @param {String} queueName
4565
- */
4566
- flush: function(queueName) {
4567
- var queueNames, idx, len, queue, log;
4756
+ hasTimers: function() {
4757
+ return !!timers.length || autorun;
4758
+ },
4568
4759
 
4569
- if (!this._queues) { return this; } // nothing to do
4760
+ cancel: function(timer) {
4761
+ if (typeof timer === 'object' && timer.queue && timer.method) { // we're cancelling a deferOnce
4762
+ return timer.queue.cancel(timer);
4763
+ } else if (typeof timer === 'function') { // we're cancelling a setTimeout
4764
+ for (var i = 0, l = timers.length; i < l; i += 2) {
4765
+ if (timers[i + 1] === timer) {
4766
+ timers.splice(i, 2); // remove the two elements
4767
+ return true;
4768
+ }
4769
+ }
4770
+ }
4771
+ }
4772
+ };
4773
+
4774
+ Backburner.prototype.schedule = Backburner.prototype.defer;
4775
+ Backburner.prototype.scheduleOnce = Backburner.prototype.deferOnce;
4776
+ Backburner.prototype.later = Backburner.prototype.setTimeout;
4570
4777
 
4571
- function iter(item) {
4572
- invoke(item.target, item.method, item.args);
4778
+ function createAutorun(backburner) {
4779
+ backburner.begin();
4780
+ autorun = setTimeout(function() {
4781
+ backburner.end();
4782
+ autorun = null;
4783
+ });
4573
4784
  }
4574
4785
 
4575
- function tryable() {
4576
- forEach.call(queue, iter);
4786
+ function executeTimers(self) {
4787
+ var now = +new Date(),
4788
+ time, fns, i, l;
4789
+
4790
+ self.run(function() {
4791
+ // TODO: binary search
4792
+ for (i = 0, l = timers.length; i < l; i += 2) {
4793
+ time = timers[i];
4794
+ if (time > now) { break; }
4795
+ }
4796
+
4797
+ fns = timers.splice(0, i);
4798
+
4799
+ for (i = 1, l = fns.length; i < l; i += 2) {
4800
+ self.schedule(self.options.defaultQueue, null, fns[i]);
4801
+ }
4802
+ });
4803
+
4804
+ if (timers.length) {
4805
+ laterTimer = setTimeout(function() {
4806
+ executeTimers(self);
4807
+ laterTimer = null;
4808
+ laterTimerExpiresAt = null;
4809
+ }, timers[0] - now);
4810
+ laterTimerExpiresAt = timers[0];
4811
+ }
4577
4812
  }
4578
4813
 
4579
- Ember.watch.flushPending(); // make sure all chained watchers are setup
4580
4814
 
4581
- if (queueName) {
4582
- while (this._queues && (queue = this._queues[queueName])) {
4583
- this._queues[queueName] = null;
4815
+ __exports__.Backburner = Backburner;
4816
+ });
4817
+
4818
+ define("backburner/deferred_action_queues",
4819
+ ["backburner/queue","exports"],
4820
+ function(__dependency1__, __exports__) {
4821
+ "use strict";
4822
+ var Queue = __dependency1__.Queue;
4823
+
4824
+ function DeferredActionQueues(queueNames, options) {
4825
+ var queues = this.queues = {};
4826
+ this.queueNames = queueNames = queueNames || [];
4584
4827
 
4585
- // the sync phase is to allow property changes to propagate. don't
4586
- // invoke observers until that is finished.
4587
- if (queueName === 'sync') {
4588
- log = Ember.LOG_BINDINGS;
4589
- if (log) { Ember.Logger.log('Begin: Flush Sync Queue'); }
4828
+ var queueName;
4829
+ for (var i = 0, l = queueNames.length; i < l; i++) {
4830
+ queueName = queueNames[i];
4831
+ queues[queueName] = new Queue(this, queueName, options[queueName]);
4832
+ }
4833
+ }
4590
4834
 
4591
- Ember.beginPropertyChanges();
4835
+ DeferredActionQueues.prototype = {
4836
+ queueNames: null,
4837
+ queues: null,
4592
4838
 
4593
- Ember.tryFinally(tryable, Ember.endPropertyChanges);
4839
+ schedule: function(queueName, target, method, args, onceFlag, stack) {
4840
+ var queues = this.queues,
4841
+ queue = queues[queueName];
4594
4842
 
4595
- if (log) { Ember.Logger.log('End: Flush Sync Queue'); }
4843
+ if (!queue) { throw new Error("You attempted to schedule an action in a queue (" + queueName + ") that doesn't exist"); }
4596
4844
 
4845
+ if (onceFlag) {
4846
+ return queue.pushUnique(target, method, args, stack);
4597
4847
  } else {
4598
- forEach.call(queue, iter);
4848
+ return queue.push(target, method, args, stack);
4849
+ }
4850
+ },
4851
+
4852
+ flush: function() {
4853
+ var queues = this.queues,
4854
+ queueNames = this.queueNames,
4855
+ queueName, queue, queueItems, priorQueueNameIndex,
4856
+ queueNameIndex = 0, numberOfQueues = queueNames.length;
4857
+
4858
+ outerloop:
4859
+ while (queueNameIndex < numberOfQueues) {
4860
+ queueName = queueNames[queueNameIndex];
4861
+ queue = queues[queueName];
4862
+ queueItems = queue._queue.slice();
4863
+ queue._queue = [];
4864
+
4865
+ var options = queue.options,
4866
+ before = options && options.before,
4867
+ after = options && options.after,
4868
+ target, method, args, stack,
4869
+ queueIndex = 0, numberOfQueueItems = queueItems.length;
4870
+
4871
+ if (numberOfQueueItems && before) { before(); }
4872
+ while (queueIndex < numberOfQueueItems) {
4873
+ target = queueItems[queueIndex];
4874
+ method = queueItems[queueIndex+1];
4875
+ args = queueItems[queueIndex+2];
4876
+ stack = queueItems[queueIndex+3]; // Debugging assistance
4877
+
4878
+ if (typeof method === 'string') { method = target[method]; }
4879
+
4880
+ // TODO: error handling
4881
+ if (args && args.length > 0) {
4882
+ method.apply(target, args);
4883
+ } else {
4884
+ method.call(target);
4885
+ }
4886
+
4887
+ queueIndex += 4;
4888
+ }
4889
+ if (numberOfQueueItems && after) { after(); }
4890
+
4891
+ if ((priorQueueNameIndex = indexOfPriorQueueWithActions(this, queueNameIndex)) !== -1) {
4892
+ queueNameIndex = priorQueueNameIndex;
4893
+ continue outerloop;
4894
+ }
4895
+
4896
+ queueNameIndex++;
4599
4897
  }
4600
4898
  }
4899
+ };
4601
4900
 
4602
- } else {
4603
- queueNames = Ember.run.queues;
4604
- len = queueNames.length;
4605
- idx = 0;
4901
+ function indexOfPriorQueueWithActions(daq, currentQueueIndex) {
4902
+ var queueName, queue;
4903
+
4904
+ for (var i = 0, l = currentQueueIndex; i <= l; i++) {
4905
+ queueName = daq.queueNames[i];
4906
+ queue = daq.queues[queueName];
4907
+ if (queue._queue.length) { return i; }
4908
+ }
4909
+
4910
+ return -1;
4911
+ }
4912
+
4913
+ __exports__.DeferredActionQueues = DeferredActionQueues;
4914
+ });
4915
+
4916
+ define("backburner/queue",
4917
+ ["exports"],
4918
+ function(__exports__) {
4919
+ "use strict";
4920
+ function Queue(daq, name, options) {
4921
+ this.daq = daq;
4922
+ this.name = name;
4923
+ this.options = options;
4924
+ this._queue = [];
4925
+ }
4926
+
4927
+ Queue.prototype = {
4928
+ daq: null,
4929
+ name: null,
4930
+ options: null,
4931
+ _queue: null,
4932
+
4933
+ push: function(target, method, args, stack) {
4934
+ var queue = this._queue;
4935
+ queue.push(target, method, args, stack);
4936
+ return {queue: this, target: target, method: method};
4937
+ },
4606
4938
 
4607
- outerloop:
4608
- while (idx < len) {
4609
- queueName = queueNames[idx];
4610
- queue = this._queues && this._queues[queueName];
4611
- delete this._queues[queueName];
4939
+ pushUnique: function(target, method, args, stack) {
4940
+ var queue = this._queue, currentTarget, currentMethod, i, l;
4612
4941
 
4613
- if (queue) {
4614
- // the sync phase is to allow property changes to propagate. don't
4615
- // invoke observers until that is finished.
4616
- if (queueName === 'sync') {
4617
- log = Ember.LOG_BINDINGS;
4618
- if (log) { Ember.Logger.log('Begin: Flush Sync Queue'); }
4942
+ for (i = 0, l = queue.length; i < l; i += 4) {
4943
+ currentTarget = queue[i];
4944
+ currentMethod = queue[i+1];
4619
4945
 
4620
- Ember.beginPropertyChanges();
4946
+ if (currentTarget === target && currentMethod === method) {
4947
+ queue[i+2] = args; // replace args
4948
+ queue[i+3] = stack; // replace stack
4949
+ return {queue: this, target: target, method: method}; // TODO: test this code path
4950
+ }
4951
+ }
4621
4952
 
4622
- Ember.tryFinally(tryable, Ember.endPropertyChanges);
4953
+ this._queue.push(target, method, args, stack);
4954
+ return {queue: this, target: target, method: method};
4955
+ },
4623
4956
 
4624
- if (log) { Ember.Logger.log('End: Flush Sync Queue'); }
4957
+ // TODO: remove me, only being used for Ember.run.sync
4958
+ flush: function() {
4959
+ var queue = this._queue,
4960
+ options = this.options,
4961
+ before = options && options.before,
4962
+ after = options && options.after,
4963
+ target, method, args, stack, i, l = queue.length;
4964
+
4965
+ if (l && before) { before(); }
4966
+ for (i = 0; i < l; i += 4) {
4967
+ target = queue[i];
4968
+ method = queue[i+1];
4969
+ args = queue[i+2];
4970
+ stack = queue[i+3]; // Debugging assistance
4971
+
4972
+ // TODO: error handling
4973
+ if (args && args.length > 0) {
4974
+ method.apply(target, args);
4625
4975
  } else {
4626
- forEach.call(queue, iter);
4976
+ method.call(target);
4627
4977
  }
4628
4978
  }
4979
+ if (l && after) { after(); }
4629
4980
 
4630
- // Loop through prior queues
4631
- for (var i = 0; i <= idx; i++) {
4632
- if (this._queues && this._queues[queueNames[i]]) {
4633
- // Start over at the first queue with contents
4634
- idx = i;
4635
- continue outerloop;
4636
- }
4981
+ // check if new items have been added
4982
+ if (queue.length > l) {
4983
+ this._queue = queue.slice(l);
4984
+ this.flush();
4985
+ } else {
4986
+ this._queue.length = 0;
4637
4987
  }
4988
+ },
4989
+
4990
+ cancel: function(actionToCancel) {
4991
+ var queue = this._queue, currentTarget, currentMethod, i, l;
4638
4992
 
4639
- idx++;
4993
+ for (i = 0, l = queue.length; i < l; i += 4) {
4994
+ currentTarget = queue[i];
4995
+ currentMethod = queue[i+1];
4996
+
4997
+ if (currentTarget === actionToCancel.target && currentMethod === actionToCancel.method) {
4998
+ queue.splice(i, 4);
4999
+ return true;
5000
+ }
5001
+ }
4640
5002
  }
4641
- }
5003
+ };
5004
+
5005
+ __exports__.Queue = Queue;
5006
+ });
5007
+
5008
+ })();
5009
+
4642
5010
 
4643
- return this;
4644
- }
4645
5011
 
5012
+ (function() {
5013
+ var onBegin = function(current) {
5014
+ Ember.run.currentRunLoop = current;
5015
+ };
5016
+
5017
+ var onEnd = function(current, next) {
5018
+ Ember.run.currentRunLoop = next;
4646
5019
  };
4647
5020
 
4648
- Ember.RunLoop = RunLoop;
5021
+ var Backburner = requireModule('backburner').Backburner,
5022
+ backburner = new Backburner(['sync', 'actions', 'destroy'], {
5023
+ sync: {
5024
+ before: Ember.beginPropertyChanges,
5025
+ after: Ember.endPropertyChanges
5026
+ },
5027
+ defaultQueue: 'actions',
5028
+ onBegin: onBegin,
5029
+ onEnd: onEnd
5030
+ }),
5031
+ slice = [].slice;
4649
5032
 
4650
5033
  // ..........................................................
4651
5034
  // Ember.run - this is ideally the only public API the dev sees
@@ -4679,20 +5062,76 @@ Ember.RunLoop = RunLoop;
4679
5062
  @return {Object} return value from invoking the passed function.
4680
5063
  */
4681
5064
  Ember.run = function(target, method) {
4682
- var args = arguments;
4683
- run.begin();
5065
+ var ret;
4684
5066
 
4685
- function tryable() {
4686
- if (target || method) {
4687
- return invoke(target, method, args, 2);
5067
+ if (Ember.onerror) {
5068
+ try {
5069
+ ret = backburner.run.apply(backburner, arguments);
5070
+ } catch (e) {
5071
+ Ember.onerror(e);
4688
5072
  }
5073
+ } else {
5074
+ ret = backburner.run.apply(backburner, arguments);
5075
+ }
5076
+
5077
+ return ret;
5078
+ };
5079
+
5080
+ /**
5081
+
5082
+ If no run-loop is present, it creates a new one. If a run loop is
5083
+ present it will queue itself to run on the existing run-loops action
5084
+ queue.
5085
+
5086
+ Please note: This is not for normal usage, and should be used sparingly.
5087
+
5088
+ If invoked when not within a run loop:
5089
+
5090
+ ```javascript
5091
+ Ember.run.join(function(){
5092
+ // creates a new run-loop
5093
+ });
5094
+ ```
5095
+
5096
+ Alternatively, if called within an existing run loop:
5097
+
5098
+ ```javascript
5099
+ Ember.run(function(){
5100
+ // creates a new run-loop
5101
+ Ember.run.join(function(){
5102
+ // joins with the existing run-loop, and queues for invocation on
5103
+ // the existing run-loops action queue.
5104
+ });
5105
+ });
5106
+ ```
5107
+
5108
+ @method join
5109
+ @namespace Ember
5110
+ @param {Object} [target] target of method to call
5111
+ @param {Function|String} method Method to invoke.
5112
+ May be a function or a string. If you pass a string
5113
+ then it will be looked up on the passed target.
5114
+ @param {Object} [args*] Any additional arguments you wish to pass to the method.
5115
+ @return {Object} return value from invoking the passed function. Please note,
5116
+ when called within an existing loop, no return value is possible.
5117
+ */
5118
+ Ember.run.join = function(target, method) {
5119
+ if (!Ember.run.currentRunLoop) {
5120
+ return Ember.run.apply(Ember.run, arguments);
4689
5121
  }
4690
5122
 
4691
- return Ember.tryFinally(tryable, run.end);
5123
+ var args = slice.call(arguments);
5124
+ args.unshift('actions');
5125
+ Ember.run.schedule.apply(Ember.run, args);
4692
5126
  };
4693
5127
 
5128
+ Ember.run.backburner = backburner;
5129
+
4694
5130
  var run = Ember.run;
4695
5131
 
5132
+ Ember.run.currentRunLoop = null;
5133
+
5134
+ Ember.run.queues = backburner.queueNames;
4696
5135
 
4697
5136
  /**
4698
5137
  Begins a new RunLoop. Any deferred actions invoked after the begin will
@@ -4709,7 +5148,7 @@ var run = Ember.run;
4709
5148
  @return {void}
4710
5149
  */
4711
5150
  Ember.run.begin = function() {
4712
- run.currentRunLoop = new RunLoop(run.currentRunLoop);
5151
+ backburner.begin();
4713
5152
  };
4714
5153
 
4715
5154
  /**
@@ -4727,12 +5166,7 @@ Ember.run.begin = function() {
4727
5166
  @return {void}
4728
5167
  */
4729
5168
  Ember.run.end = function() {
4730
- Ember.assert('must have a current run loop', run.currentRunLoop);
4731
-
4732
- function tryable() { run.currentRunLoop.end(); }
4733
- function finalizer() { run.currentRunLoop = run.currentRunLoop.prev(); }
4734
-
4735
- Ember.tryFinally(tryable, finalizer);
5169
+ backburner.end();
4736
5170
  };
4737
5171
 
4738
5172
  /**
@@ -4745,7 +5179,6 @@ Ember.run.end = function() {
4745
5179
  @type Array
4746
5180
  @default ['sync', 'actions', 'destroy']
4747
5181
  */
4748
- Ember.run.queues = ['sync', 'actions', 'destroy'];
4749
5182
 
4750
5183
  /**
4751
5184
  Adds the passed target/method and any optional arguments to the named
@@ -4784,57 +5217,18 @@ Ember.run.queues = ['sync', 'actions', 'destroy'];
4784
5217
  @return {void}
4785
5218
  */
4786
5219
  Ember.run.schedule = function(queue, target, method) {
4787
- var loop = run.autorun();
4788
- loop.schedule.apply(loop, arguments);
5220
+ checkAutoRun();
5221
+ backburner.schedule.apply(backburner, arguments);
4789
5222
  };
4790
5223
 
4791
- var scheduledAutorun;
4792
- function autorun() {
4793
- scheduledAutorun = null;
4794
- if (run.currentRunLoop) { run.end(); }
4795
- }
4796
-
4797
5224
  // Used by global test teardown
4798
5225
  Ember.run.hasScheduledTimers = function() {
4799
- return !!(scheduledAutorun || scheduledLater);
5226
+ return backburner.hasTimers();
4800
5227
  };
4801
5228
 
4802
5229
  // Used by global test teardown
4803
5230
  Ember.run.cancelTimers = function () {
4804
- if (scheduledAutorun) {
4805
- clearTimeout(scheduledAutorun);
4806
- scheduledAutorun = null;
4807
- }
4808
- if (scheduledLater) {
4809
- clearTimeout(scheduledLater);
4810
- scheduledLater = null;
4811
- }
4812
- timers = {};
4813
- };
4814
-
4815
- /**
4816
- Begins a new RunLoop if necessary and schedules a timer to flush the
4817
- RunLoop at a later time. This method is used by parts of Ember to
4818
- ensure the RunLoop always finishes. You normally do not need to call this
4819
- method directly. Instead use `Ember.run()`
4820
-
4821
- @method autorun
4822
- @example
4823
- Ember.run.autorun();
4824
- @return {Ember.RunLoop} the new current RunLoop
4825
- */
4826
- Ember.run.autorun = function() {
4827
- if (!run.currentRunLoop) {
4828
- Ember.assert("You have turned on testing mode, which disabled the run-loop's autorun. You will need to wrap any code with asynchronous side-effects in an Ember.run", !Ember.testing);
4829
-
4830
- run.begin();
4831
-
4832
- if (!scheduledAutorun) {
4833
- scheduledAutorun = setTimeout(autorun, 1);
4834
- }
4835
- }
4836
-
4837
- return run.currentRunLoop;
5231
+ backburner.cancelTimers();
4838
5232
  };
4839
5233
 
4840
5234
  /**
@@ -4854,42 +5248,9 @@ Ember.run.autorun = function() {
4854
5248
  @return {void}
4855
5249
  */
4856
5250
  Ember.run.sync = function() {
4857
- run.autorun();
4858
- run.currentRunLoop.flush('sync');
5251
+ backburner.currentInstance.queues.sync.flush();
4859
5252
  };
4860
5253
 
4861
- // ..........................................................
4862
- // TIMERS
4863
- //
4864
-
4865
- var timers = {}; // active timers...
4866
-
4867
- var scheduledLater, scheduledLaterExpires;
4868
- function invokeLaterTimers() {
4869
- scheduledLater = null;
4870
- run(function() {
4871
- var now = (+ new Date()), earliest = -1;
4872
- for (var key in timers) {
4873
- if (!timers.hasOwnProperty(key)) { continue; }
4874
- var timer = timers[key];
4875
- if (timer && timer.expires) {
4876
- if (now >= timer.expires) {
4877
- delete timers[key];
4878
- invoke(timer.target, timer.method, timer.args, 2);
4879
- } else {
4880
- if (earliest < 0 || (timer.expires < earliest)) { earliest = timer.expires; }
4881
- }
4882
- }
4883
- }
4884
-
4885
- // schedule next timeout to fire when the earliest timer expires
4886
- if (earliest > 0) {
4887
- scheduledLater = setTimeout(invokeLaterTimers, earliest - now);
4888
- scheduledLaterExpires = earliest;
4889
- }
4890
- });
4891
- }
4892
-
4893
5254
  /**
4894
5255
  Invokes the passed target/method and optional arguments after a specified
4895
5256
  period if time. The last parameter of this method must always be a number
@@ -4901,89 +5262,24 @@ function invokeLaterTimers() {
4901
5262
  together, which is often more efficient than using a real setTimeout.
4902
5263
 
4903
5264
  ```javascript
4904
- Ember.run.later(myContext, function(){
4905
- // code here will execute within a RunLoop in about 500ms with this == myContext
4906
- }, 500);
4907
- ```
4908
-
4909
- @method later
4910
- @param {Object} [target] target of method to invoke
4911
- @param {Function|String} method The method to invoke.
4912
- If you pass a string it will be resolved on the
4913
- target at the time the method is invoked.
4914
- @param {Object} [args*] Optional arguments to pass to the timeout.
4915
- @param {Number} wait Number of milliseconds to wait.
4916
- @return {String} a string you can use to cancel the timer in
4917
- {{#crossLink "Ember/run.cancel"}}{{/crossLink}} later.
4918
- */
4919
- Ember.run.later = function(target, method) {
4920
- var args, expires, timer, guid, wait;
4921
-
4922
- // setTimeout compatibility...
4923
- if (arguments.length===2 && 'function' === typeof target) {
4924
- wait = method;
4925
- method = target;
4926
- target = undefined;
4927
- args = [target, method];
4928
- } else {
4929
- args = slice.call(arguments);
4930
- wait = args.pop();
4931
- }
4932
-
4933
- expires = (+ new Date()) + wait;
4934
- timer = { target: target, method: method, expires: expires, args: args };
4935
- guid = Ember.guidFor(timer);
4936
- timers[guid] = timer;
4937
-
4938
- if(scheduledLater && expires < scheduledLaterExpires) {
4939
- // Cancel later timer (then reschedule earlier timer below)
4940
- clearTimeout(scheduledLater);
4941
- scheduledLater = null;
4942
- }
4943
-
4944
- if (!scheduledLater) {
4945
- // Schedule later timers to be run.
4946
- scheduledLater = setTimeout(invokeLaterTimers, wait);
4947
- scheduledLaterExpires = expires;
4948
- }
4949
-
4950
- return guid;
4951
- };
4952
-
4953
- function invokeOnceTimer(guid, onceTimers) {
4954
- if (onceTimers[this.tguid]) { delete onceTimers[this.tguid][this.mguid]; }
4955
- if (timers[guid]) { invoke(this.target, this.method, this.args); }
4956
- delete timers[guid];
4957
- }
4958
-
4959
- function scheduleOnce(queue, target, method, args) {
4960
- var tguid = Ember.guidFor(target),
4961
- mguid = Ember.guidFor(method),
4962
- onceTimers = run.autorun().onceTimers,
4963
- guid = onceTimers[tguid] && onceTimers[tguid][mguid],
4964
- timer;
4965
-
4966
- if (guid && timers[guid]) {
4967
- timers[guid].args = args; // replace args
4968
- } else {
4969
- timer = {
4970
- target: target,
4971
- method: method,
4972
- args: args,
4973
- tguid: tguid,
4974
- mguid: mguid
4975
- };
4976
-
4977
- guid = Ember.guidFor(timer);
4978
- timers[guid] = timer;
4979
- if (!onceTimers[tguid]) { onceTimers[tguid] = {}; }
4980
- onceTimers[tguid][mguid] = guid; // so it isn't scheduled more than once
4981
-
4982
- run.schedule(queue, timer, invokeOnceTimer, guid, onceTimers);
4983
- }
5265
+ Ember.run.later(myContext, function(){
5266
+ // code here will execute within a RunLoop in about 500ms with this == myContext
5267
+ }, 500);
5268
+ ```
4984
5269
 
4985
- return guid;
4986
- }
5270
+ @method later
5271
+ @param {Object} [target] target of method to invoke
5272
+ @param {Function|String} method The method to invoke.
5273
+ If you pass a string it will be resolved on the
5274
+ target at the time the method is invoked.
5275
+ @param {Object} [args*] Optional arguments to pass to the timeout.
5276
+ @param {Number} wait Number of milliseconds to wait.
5277
+ @return {String} a string you can use to cancel the timer in
5278
+ `Ember.run.cancel` later.
5279
+ */
5280
+ Ember.run.later = function(target, method) {
5281
+ return backburner.later.apply(backburner, arguments);
5282
+ };
4987
5283
 
4988
5284
  /**
4989
5285
  Schedule a function to run one time during the current RunLoop. This is equivalent
@@ -4998,7 +5294,10 @@ function scheduleOnce(queue, target, method, args) {
4998
5294
  @return {Object} timer
4999
5295
  */
5000
5296
  Ember.run.once = function(target, method) {
5001
- return scheduleOnce('actions', target, method, slice.call(arguments, 2));
5297
+ checkAutoRun();
5298
+ var args = slice.call(arguments);
5299
+ args.unshift('actions');
5300
+ return backburner.scheduleOnce.apply(backburner, args);
5002
5301
  };
5003
5302
 
5004
5303
  /**
@@ -5046,12 +5345,13 @@ Ember.run.once = function(target, method) {
5046
5345
  @return {Object} timer
5047
5346
  */
5048
5347
  Ember.run.scheduleOnce = function(queue, target, method) {
5049
- return scheduleOnce(queue, target, method, slice.call(arguments, 3));
5348
+ checkAutoRun();
5349
+ return backburner.scheduleOnce.apply(backburner, arguments);
5050
5350
  };
5051
5351
 
5052
5352
  /**
5053
- Schedules an item to run from within a separate run loop, after
5054
- control has been returned to the system. This is equivalent to calling
5353
+ Schedules an item to run from within a separate run loop, after
5354
+ control has been returned to the system. This is equivalent to calling
5055
5355
  `Ember.run.later` with a wait time of 1ms.
5056
5356
 
5057
5357
  ```javascript
@@ -5063,7 +5363,7 @@ Ember.run.scheduleOnce = function(queue, target, method) {
5063
5363
  Multiple operations scheduled with `Ember.run.next` will coalesce
5064
5364
  into the same later run loop, along with any other operations
5065
5365
  scheduled by `Ember.run.later` that expire right around the same
5066
- time that `Ember.run.next` operations will fire.
5366
+ time that `Ember.run.next` operations will fire.
5067
5367
 
5068
5368
  Note that there are often alternatives to using `Ember.run.next`.
5069
5369
  For instance, if you'd like to schedule an operation to happen
@@ -5089,13 +5389,13 @@ Ember.run.scheduleOnce = function(queue, target, method) {
5089
5389
 
5090
5390
  One benefit of the above approach compared to using `Ember.run.next` is
5091
5391
  that you will be able to perform DOM/CSS operations before unprocessed
5092
- elements are rendered to the screen, which may prevent flickering or
5392
+ elements are rendered to the screen, which may prevent flickering or
5093
5393
  other artifacts caused by delaying processing until after rendering.
5094
5394
 
5095
- The other major benefit to the above approach is that `Ember.run.next`
5096
- introduces an element of non-determinism, which can make things much
5097
- harder to test, due to its reliance on `setTimeout`; it's much harder
5098
- to guarantee the order of scheduled operations when they are scheduled
5395
+ The other major benefit to the above approach is that `Ember.run.next`
5396
+ introduces an element of non-determinism, which can make things much
5397
+ harder to test, due to its reliance on `setTimeout`; it's much harder
5398
+ to guarantee the order of scheduled operations when they are scheduled
5099
5399
  outside of the current run loop, i.e. with `Ember.run.next`.
5100
5400
 
5101
5401
  @method next
@@ -5108,8 +5408,8 @@ Ember.run.scheduleOnce = function(queue, target, method) {
5108
5408
  */
5109
5409
  Ember.run.next = function() {
5110
5410
  var args = slice.call(arguments);
5111
- args.push(1); // 1 millisecond wait
5112
- return run.later.apply(this, args);
5411
+ args.push(1);
5412
+ return backburner.later.apply(backburner, args);
5113
5413
  };
5114
5414
 
5115
5415
  /**
@@ -5138,9 +5438,16 @@ Ember.run.next = function() {
5138
5438
  @return {void}
5139
5439
  */
5140
5440
  Ember.run.cancel = function(timer) {
5141
- delete timers[timer];
5441
+ return backburner.cancel(timer);
5142
5442
  };
5143
5443
 
5444
+ // Make sure it's not an autorun during testing
5445
+ function checkAutoRun() {
5446
+ if (!Ember.run.currentRunLoop) {
5447
+ Ember.assert("You have turned on testing mode, which disabled the run-loop's autorun. You will need to wrap any code with asynchronous side-effects in an Ember.run", !Ember.testing);
5448
+ }
5449
+ }
5450
+
5144
5451
  })();
5145
5452
 
5146
5453
 
@@ -5425,7 +5732,7 @@ function mixinProperties(to, from) {
5425
5732
  mixinProperties(Binding, {
5426
5733
 
5427
5734
  /**
5428
- See {{#crossLink "Ember.Binding/from"}}{{/crossLink}}
5735
+ See `Ember.Binding.from`.
5429
5736
 
5430
5737
  @method from
5431
5738
  @static
@@ -5436,7 +5743,7 @@ mixinProperties(Binding, {
5436
5743
  },
5437
5744
 
5438
5745
  /**
5439
- See {{#crossLink "Ember.Binding/to"}}{{/crossLink}}
5746
+ See `Ember.Binding.to`.
5440
5747
 
5441
5748
  @method to
5442
5749
  @static
@@ -5453,7 +5760,7 @@ mixinProperties(Binding, {
5453
5760
  This means that if you change the "to" side directly, the "from" side may have
5454
5761
  a different value.
5455
5762
 
5456
- See {{#crossLink "Binding/oneWay"}}{{/crossLink}}
5763
+ See `Binding.oneWay`.
5457
5764
 
5458
5765
  @method oneWay
5459
5766
  @param {String} from from path.
@@ -5514,7 +5821,7 @@ mixinProperties(Binding, {
5514
5821
 
5515
5822
  You should consider using one way bindings anytime you have an object that
5516
5823
  may be created frequently and you do not intend to change a property; only
5517
- to monitor it for changes. (such as in the example above).
5824
+ to monitor it for changes (such as in the example above).
5518
5825
 
5519
5826
  ## Adding Bindings Manually
5520
5827
 
@@ -5815,14 +6122,6 @@ function mergeMixins(mixins, m, descs, values, base, keys) {
5815
6122
  }
5816
6123
  }
5817
6124
 
5818
- function writableReq(obj) {
5819
- var m = Ember.meta(obj), req = m.required;
5820
- if (!req || !m.hasOwnProperty('required')) {
5821
- req = m.required = req ? o_create(req) : {};
5822
- }
5823
- return req;
5824
- }
5825
-
5826
6125
  var IS_BINDING = Ember.IS_BINDING = /^.+Binding$/;
5827
6126
 
5828
6127
  function detectBinding(obj, key, value, m) {
@@ -6308,14 +6607,57 @@ Ember Metal
6308
6607
  })();
6309
6608
 
6310
6609
  (function() {
6311
- define("rsvp",
6312
- [],
6313
- function() {
6610
+ define("rsvp/all",
6611
+ ["rsvp/defer","exports"],
6612
+ function(__dependency1__, __exports__) {
6613
+ "use strict";
6614
+ var defer = __dependency1__.defer;
6615
+
6616
+ function all(promises) {
6617
+ var results = [], deferred = defer(), remaining = promises.length;
6618
+
6619
+ if (remaining === 0) {
6620
+ deferred.resolve([]);
6621
+ }
6622
+
6623
+ var resolver = function(index) {
6624
+ return function(value) {
6625
+ resolveAll(index, value);
6626
+ };
6627
+ };
6628
+
6629
+ var resolveAll = function(index, value) {
6630
+ results[index] = value;
6631
+ if (--remaining === 0) {
6632
+ deferred.resolve(results);
6633
+ }
6634
+ };
6635
+
6636
+ var rejectAll = function(error) {
6637
+ deferred.reject(error);
6638
+ };
6639
+
6640
+ for (var i = 0; i < promises.length; i++) {
6641
+ if (promises[i] && typeof promises[i].then === 'function') {
6642
+ promises[i].then(resolver(i), rejectAll);
6643
+ } else {
6644
+ resolveAll(i, promises[i]);
6645
+ }
6646
+ }
6647
+ return deferred.promise;
6648
+ }
6649
+
6650
+ __exports__.all = all;
6651
+ });
6652
+
6653
+ define("rsvp/async",
6654
+ ["exports"],
6655
+ function(__exports__) {
6314
6656
  "use strict";
6315
6657
  var browserGlobal = (typeof window !== 'undefined') ? window : {};
6316
6658
 
6317
- var MutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;
6318
- var RSVP, async;
6659
+ var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;
6660
+ var async;
6319
6661
 
6320
6662
  if (typeof process !== 'undefined' &&
6321
6663
  {}.toString.call(process) === '[object process]') {
@@ -6324,10 +6666,10 @@ define("rsvp",
6324
6666
  callback.call(binding);
6325
6667
  });
6326
6668
  };
6327
- } else if (MutationObserver) {
6669
+ } else if (BrowserMutationObserver) {
6328
6670
  var queue = [];
6329
6671
 
6330
- var observer = new MutationObserver(function() {
6672
+ var observer = new BrowserMutationObserver(function() {
6331
6673
  var toProcess = queue.slice();
6332
6674
  queue = [];
6333
6675
 
@@ -6358,6 +6700,47 @@ define("rsvp",
6358
6700
  };
6359
6701
  }
6360
6702
 
6703
+
6704
+ __exports__.async = async;
6705
+ });
6706
+
6707
+ define("rsvp/config",
6708
+ ["rsvp/async","exports"],
6709
+ function(__dependency1__, __exports__) {
6710
+ "use strict";
6711
+ var async = __dependency1__.async;
6712
+
6713
+ var config = {};
6714
+ config.async = async;
6715
+
6716
+ __exports__.config = config;
6717
+ });
6718
+
6719
+ define("rsvp/defer",
6720
+ ["rsvp/promise","exports"],
6721
+ function(__dependency1__, __exports__) {
6722
+ "use strict";
6723
+ var Promise = __dependency1__.Promise;
6724
+
6725
+ function defer() {
6726
+ var deferred = {};
6727
+
6728
+ var promise = new Promise(function(resolve, reject) {
6729
+ deferred.resolve = resolve;
6730
+ deferred.reject = reject;
6731
+ });
6732
+
6733
+ deferred.promise = promise;
6734
+ return deferred;
6735
+ }
6736
+
6737
+ __exports__.defer = defer;
6738
+ });
6739
+
6740
+ define("rsvp/events",
6741
+ ["exports"],
6742
+ function(__exports__) {
6743
+ "use strict";
6361
6744
  var Event = function(type, options) {
6362
6745
  this.type = type;
6363
6746
 
@@ -6452,7 +6835,148 @@ define("rsvp",
6452
6835
  }
6453
6836
  };
6454
6837
 
6455
- var Promise = function() {
6838
+
6839
+ __exports__.EventTarget = EventTarget;
6840
+ });
6841
+
6842
+ define("rsvp/hash",
6843
+ ["rsvp/defer","exports"],
6844
+ function(__dependency1__, __exports__) {
6845
+ "use strict";
6846
+ var defer = __dependency1__.defer;
6847
+
6848
+ function size(object) {
6849
+ var size = 0;
6850
+
6851
+ for (var prop in object) {
6852
+ size++;
6853
+ }
6854
+
6855
+ return size;
6856
+ }
6857
+
6858
+ function hash(promises) {
6859
+ var results = {}, deferred = defer(), remaining = size(promises);
6860
+
6861
+ if (remaining === 0) {
6862
+ deferred.resolve({});
6863
+ }
6864
+
6865
+ var resolver = function(prop) {
6866
+ return function(value) {
6867
+ resolveAll(prop, value);
6868
+ };
6869
+ };
6870
+
6871
+ var resolveAll = function(prop, value) {
6872
+ results[prop] = value;
6873
+ if (--remaining === 0) {
6874
+ deferred.resolve(results);
6875
+ }
6876
+ };
6877
+
6878
+ var rejectAll = function(error) {
6879
+ deferred.reject(error);
6880
+ };
6881
+
6882
+ for (var prop in promises) {
6883
+ if (promises[prop] && typeof promises[prop].then === 'function') {
6884
+ promises[prop].then(resolver(prop), rejectAll);
6885
+ } else {
6886
+ resolveAll(prop, promises[prop]);
6887
+ }
6888
+ }
6889
+
6890
+ return deferred.promise;
6891
+ }
6892
+
6893
+ __exports__.hash = hash;
6894
+ });
6895
+
6896
+ define("rsvp/node",
6897
+ ["rsvp/promise","rsvp/all","exports"],
6898
+ function(__dependency1__, __dependency2__, __exports__) {
6899
+ "use strict";
6900
+ var Promise = __dependency1__.Promise;
6901
+ var all = __dependency2__.all;
6902
+
6903
+ function makeNodeCallbackFor(resolve, reject) {
6904
+ return function (error, value) {
6905
+ if (error) {
6906
+ reject(error);
6907
+ } else if (arguments.length > 2) {
6908
+ resolve(Array.prototype.slice.call(arguments, 1));
6909
+ } else {
6910
+ resolve(value);
6911
+ }
6912
+ };
6913
+ }
6914
+
6915
+ function denodeify(nodeFunc) {
6916
+ return function() {
6917
+ var nodeArgs = Array.prototype.slice.call(arguments), resolve, reject;
6918
+
6919
+ var promise = new Promise(function(nodeResolve, nodeReject) {
6920
+ resolve = nodeResolve;
6921
+ reject = nodeReject;
6922
+ });
6923
+
6924
+ all(nodeArgs).then(function(nodeArgs) {
6925
+ nodeArgs.push(makeNodeCallbackFor(resolve, reject));
6926
+
6927
+ try {
6928
+ nodeFunc.apply(this, nodeArgs);
6929
+ } catch(e) {
6930
+ reject(e);
6931
+ }
6932
+ });
6933
+
6934
+ return promise;
6935
+ };
6936
+ }
6937
+
6938
+ __exports__.denodeify = denodeify;
6939
+ });
6940
+
6941
+ define("rsvp/promise",
6942
+ ["rsvp/config","rsvp/events","exports"],
6943
+ function(__dependency1__, __dependency2__, __exports__) {
6944
+ "use strict";
6945
+ var config = __dependency1__.config;
6946
+ var EventTarget = __dependency2__.EventTarget;
6947
+
6948
+ function objectOrFunction(x) {
6949
+ return isFunction(x) || (typeof x === "object" && x !== null);
6950
+ }
6951
+
6952
+ function isFunction(x){
6953
+ return typeof x === "function";
6954
+ }
6955
+
6956
+ var Promise = function(resolver) {
6957
+ var promise = this,
6958
+ resolved = false;
6959
+
6960
+ if (typeof resolver !== 'function') {
6961
+ throw new TypeError('You must pass a resolver function as the sole argument to the promise constructor');
6962
+ }
6963
+
6964
+ if (!(promise instanceof Promise)) {
6965
+ return new Promise(resolver);
6966
+ }
6967
+
6968
+ var resolvePromise = function(value) {
6969
+ if (resolved) { return; }
6970
+ resolved = true;
6971
+ resolve(promise, value);
6972
+ };
6973
+
6974
+ var rejectPromise = function(value) {
6975
+ if (resolved) { return; }
6976
+ resolved = true;
6977
+ reject(promise, value);
6978
+ };
6979
+
6456
6980
  this.on('promise:resolved', function(event) {
6457
6981
  this.trigger('success', { detail: event.detail });
6458
6982
  }, this);
@@ -6460,12 +6984,16 @@ define("rsvp",
6460
6984
  this.on('promise:failed', function(event) {
6461
6985
  this.trigger('error', { detail: event.detail });
6462
6986
  }, this);
6463
- };
6464
6987
 
6465
- var noop = function() {};
6988
+ try {
6989
+ resolver(resolvePromise, rejectPromise);
6990
+ } catch(e) {
6991
+ rejectPromise(e);
6992
+ }
6993
+ };
6466
6994
 
6467
6995
  var invokeCallback = function(type, promise, callback, event) {
6468
- var hasCallback = typeof callback === 'function',
6996
+ var hasCallback = isFunction(callback),
6469
6997
  value, error, succeeded, failed;
6470
6998
 
6471
6999
  if (hasCallback) {
@@ -6481,34 +7009,34 @@ define("rsvp",
6481
7009
  succeeded = true;
6482
7010
  }
6483
7011
 
6484
- if (value && typeof value.then === 'function') {
6485
- value.then(function(value) {
6486
- promise.resolve(value);
6487
- }, function(error) {
6488
- promise.reject(error);
6489
- });
7012
+ if (handleThenable(promise, value)) {
7013
+ return;
6490
7014
  } else if (hasCallback && succeeded) {
6491
- promise.resolve(value);
7015
+ resolve(promise, value);
6492
7016
  } else if (failed) {
6493
- promise.reject(error);
6494
- } else {
6495
- promise[type](value);
7017
+ reject(promise, error);
7018
+ } else if (type === 'resolve') {
7019
+ resolve(promise, value);
7020
+ } else if (type === 'reject') {
7021
+ reject(promise, value);
6496
7022
  }
6497
7023
  };
6498
7024
 
6499
7025
  Promise.prototype = {
7026
+ constructor: Promise,
7027
+
6500
7028
  then: function(done, fail) {
6501
- var thenPromise = new Promise();
7029
+ var thenPromise = new Promise(function() {});
6502
7030
 
6503
- if (this.isResolved) {
6504
- RSVP.async(function() {
6505
- invokeCallback('resolve', thenPromise, done, { detail: this.resolvedValue });
7031
+ if (this.isFulfilled) {
7032
+ config.async(function() {
7033
+ invokeCallback('resolve', thenPromise, done, { detail: this.fulfillmentValue });
6506
7034
  }, this);
6507
7035
  }
6508
7036
 
6509
7037
  if (this.isRejected) {
6510
- RSVP.async(function() {
6511
- invokeCallback('reject', thenPromise, fail, { detail: this.rejectedValue });
7038
+ config.async(function() {
7039
+ invokeCallback('reject', thenPromise, fail, { detail: this.rejectedReason });
6512
7040
  }, this);
6513
7041
  }
6514
7042
 
@@ -6521,75 +7049,162 @@ define("rsvp",
6521
7049
  });
6522
7050
 
6523
7051
  return thenPromise;
6524
- },
7052
+ }
7053
+ };
6525
7054
 
6526
- resolve: function(value) {
6527
- resolve(this, value);
7055
+ EventTarget.mixin(Promise.prototype);
6528
7056
 
6529
- this.resolve = noop;
6530
- this.reject = noop;
6531
- },
7057
+ function resolve(promise, value) {
7058
+ if (promise === value) {
7059
+ fulfill(promise, value);
7060
+ } else if (!handleThenable(promise, value)) {
7061
+ fulfill(promise, value);
7062
+ }
7063
+ }
7064
+
7065
+ function handleThenable(promise, value) {
7066
+ var then = null;
6532
7067
 
6533
- reject: function(value) {
6534
- reject(this, value);
7068
+ if (objectOrFunction(value)) {
7069
+ try {
7070
+ then = value.then;
7071
+ } catch(e) {
7072
+ reject(promise, e);
7073
+ return true;
7074
+ }
6535
7075
 
6536
- this.resolve = noop;
6537
- this.reject = noop;
7076
+ if (isFunction(then)) {
7077
+ try {
7078
+ then.call(value, function(val) {
7079
+ if (value !== val) {
7080
+ resolve(promise, val);
7081
+ } else {
7082
+ fulfill(promise, val);
7083
+ }
7084
+ }, function(val) {
7085
+ reject(promise, val);
7086
+ });
7087
+ } catch (e) {
7088
+ reject(promise, e);
7089
+ }
7090
+ return true;
7091
+ }
6538
7092
  }
6539
- };
6540
7093
 
6541
- function resolve(promise, value) {
6542
- RSVP.async(function() {
7094
+ return false;
7095
+ }
7096
+
7097
+ function fulfill(promise, value) {
7098
+ config.async(function() {
6543
7099
  promise.trigger('promise:resolved', { detail: value });
6544
- promise.isResolved = true;
6545
- promise.resolvedValue = value;
7100
+ promise.isFulfilled = true;
7101
+ promise.fulfillmentValue = value;
6546
7102
  });
6547
7103
  }
6548
7104
 
6549
7105
  function reject(promise, value) {
6550
- RSVP.async(function() {
7106
+ config.async(function() {
6551
7107
  promise.trigger('promise:failed', { detail: value });
6552
7108
  promise.isRejected = true;
6553
- promise.rejectedValue = value;
7109
+ promise.rejectedReason = value;
6554
7110
  });
6555
7111
  }
6556
7112
 
6557
- function all(promises) {
6558
- var i, results = [];
6559
- var allPromise = new Promise();
6560
- var remaining = promises.length;
6561
7113
 
6562
- if (remaining === 0) {
6563
- allPromise.resolve([]);
6564
- }
7114
+ __exports__.Promise = Promise;
7115
+ });
6565
7116
 
6566
- var resolver = function(index) {
6567
- return function(value) {
6568
- resolve(index, value);
6569
- };
6570
- };
7117
+ define("rsvp/reject",
7118
+ ["rsvp/promise","exports"],
7119
+ function(__dependency1__, __exports__) {
7120
+ "use strict";
7121
+ var Promise = __dependency1__.Promise;
6571
7122
 
6572
- var resolve = function(index, value) {
6573
- results[index] = value;
6574
- if (--remaining === 0) {
6575
- allPromise.resolve(results);
6576
- }
6577
- };
6578
7123
 
6579
- var reject = function(error) {
6580
- allPromise.reject(error);
6581
- };
7124
+ function objectOrFunction(x) {
7125
+ return typeof x === "function" || (typeof x === "object" && x !== null);
7126
+ }
6582
7127
 
6583
- for (i = 0; i < remaining; i++) {
6584
- promises[i].then(resolver(i), reject);
6585
- }
6586
- return allPromise;
7128
+
7129
+ function reject(reason) {
7130
+ return new Promise(function (resolve, reject) {
7131
+ reject(reason);
7132
+ });
6587
7133
  }
6588
7134
 
6589
- EventTarget.mixin(Promise.prototype);
6590
7135
 
6591
- RSVP = { async: async, Promise: Promise, Event: Event, EventTarget: EventTarget, all: all, raiseOnUncaughtExceptions: true };
6592
- return RSVP;
7136
+ __exports__.reject = reject;
7137
+ });
7138
+
7139
+ define("rsvp/resolve",
7140
+ ["rsvp/promise","exports"],
7141
+ function(__dependency1__, __exports__) {
7142
+ "use strict";
7143
+ var Promise = __dependency1__.Promise;
7144
+
7145
+
7146
+ function objectOrFunction(x) {
7147
+ return typeof x === "function" || (typeof x === "object" && x !== null);
7148
+ }
7149
+
7150
+ function resolve(thenable){
7151
+ var promise = new Promise(function(resolve, reject){
7152
+ var then;
7153
+
7154
+ try {
7155
+ if ( objectOrFunction(thenable) ) {
7156
+ then = thenable.then;
7157
+
7158
+ if (typeof then === "function") {
7159
+ then.call(thenable, resolve, reject);
7160
+ } else {
7161
+ resolve(thenable);
7162
+ }
7163
+
7164
+ } else {
7165
+ resolve(thenable);
7166
+ }
7167
+
7168
+ } catch(error) {
7169
+ reject(error);
7170
+ }
7171
+ });
7172
+
7173
+ return promise;
7174
+ }
7175
+
7176
+
7177
+ __exports__.resolve = resolve;
7178
+ });
7179
+
7180
+ define("rsvp",
7181
+ ["rsvp/events","rsvp/promise","rsvp/node","rsvp/all","rsvp/hash","rsvp/defer","rsvp/config","rsvp/resolve","rsvp/reject","exports"],
7182
+ function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __exports__) {
7183
+ "use strict";
7184
+ var EventTarget = __dependency1__.EventTarget;
7185
+ var Promise = __dependency2__.Promise;
7186
+ var denodeify = __dependency3__.denodeify;
7187
+ var all = __dependency4__.all;
7188
+ var hash = __dependency5__.hash;
7189
+ var defer = __dependency6__.defer;
7190
+ var config = __dependency7__.config;
7191
+ var resolve = __dependency8__.resolve;
7192
+ var reject = __dependency9__.reject;
7193
+
7194
+ function configure(name, value) {
7195
+ config[name] = value;
7196
+ }
7197
+
7198
+
7199
+ __exports__.Promise = Promise;
7200
+ __exports__.EventTarget = EventTarget;
7201
+ __exports__.all = all;
7202
+ __exports__.hash = hash;
7203
+ __exports__.defer = defer;
7204
+ __exports__.denodeify = denodeify;
7205
+ __exports__.configure = configure;
7206
+ __exports__.resolve = resolve;
7207
+ __exports__.reject = reject;
6593
7208
  });
6594
7209
 
6595
7210
  })();
@@ -6765,10 +7380,6 @@ define("container",
6765
7380
 
6766
7381
  this.children = [];
6767
7382
 
6768
- eachDestroyable(this, function(item) {
6769
- item.isDestroying = true;
6770
- });
6771
-
6772
7383
  eachDestroyable(this, function(item) {
6773
7384
  item.destroy();
6774
7385
  });
@@ -7140,10 +7751,15 @@ Ember.ORDER_DEFINITION = Ember.ENV.ORDER_DEFINITION || [
7140
7751
  */
7141
7752
  Ember.keys = Object.keys;
7142
7753
 
7143
- if (!Ember.keys) {
7754
+ if (!Ember.keys || Ember.create.isSimulated) {
7144
7755
  Ember.keys = function(obj) {
7145
7756
  var ret = [];
7146
7757
  for(var key in obj) {
7758
+ // Prevents browsers that don't respect non-enumerability from
7759
+ // copying internal Ember properties
7760
+ if (key.substring(0,2) === '__') continue;
7761
+ if (key === '_super') continue;
7762
+
7147
7763
  if (obj.hasOwnProperty(key)) { ret.push(key); }
7148
7764
  }
7149
7765
  return ret;
@@ -7165,7 +7781,7 @@ var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'n
7165
7781
  @constructor
7166
7782
  */
7167
7783
  Ember.Error = function() {
7168
- var tmp = Error.prototype.constructor.apply(this, arguments);
7784
+ var tmp = Error.apply(this, arguments);
7169
7785
 
7170
7786
  // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work.
7171
7787
  for (var idx = 0; idx < errorProps.length; idx++) {
@@ -7427,10 +8043,12 @@ Ember.String = {
7427
8043
  /**
7428
8044
  Returns the Capitalized form of a string
7429
8045
 
7430
- 'innerHTML'.capitalize() // 'InnerHTML'
7431
- 'action_name'.capitalize() // 'Action_name'
7432
- 'css-class-name'.capitalize() // 'Css-class-name'
7433
- 'my favorite items'.capitalize() // 'My favorite items'
8046
+ ```javascript
8047
+ 'innerHTML'.capitalize() // 'InnerHTML'
8048
+ 'action_name'.capitalize() // 'Action_name'
8049
+ 'css-class-name'.capitalize() // 'Css-class-name'
8050
+ 'my favorite items'.capitalize() // 'My favorite items'
8051
+ ```
7434
8052
 
7435
8053
  @method capitalize
7436
8054
  @param {String} str
@@ -7467,7 +8085,7 @@ var fmt = Ember.String.fmt,
7467
8085
  if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.String) {
7468
8086
 
7469
8087
  /**
7470
- See {{#crossLink "Ember.String/fmt"}}{{/crossLink}}
8088
+ See `Ember.String.fmt`.
7471
8089
 
7472
8090
  @method fmt
7473
8091
  @for String
@@ -7477,7 +8095,7 @@ if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.String) {
7477
8095
  };
7478
8096
 
7479
8097
  /**
7480
- See {{#crossLink "Ember.String/w"}}{{/crossLink}}
8098
+ See `Ember.String.w`.
7481
8099
 
7482
8100
  @method w
7483
8101
  @for String
@@ -7487,7 +8105,7 @@ if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.String) {
7487
8105
  };
7488
8106
 
7489
8107
  /**
7490
- See {{#crossLink "Ember.String/loc"}}{{/crossLink}}
8108
+ See `Ember.String.loc`.
7491
8109
 
7492
8110
  @method loc
7493
8111
  @for String
@@ -7497,7 +8115,7 @@ if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.String) {
7497
8115
  };
7498
8116
 
7499
8117
  /**
7500
- See {{#crossLink "Ember.String/camelize"}}{{/crossLink}}
8118
+ See `Ember.String.camelize`.
7501
8119
 
7502
8120
  @method camelize
7503
8121
  @for String
@@ -7507,7 +8125,7 @@ if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.String) {
7507
8125
  };
7508
8126
 
7509
8127
  /**
7510
- See {{#crossLink "Ember.String/decamelize"}}{{/crossLink}}
8128
+ See `Ember.String.decamelize`.
7511
8129
 
7512
8130
  @method decamelize
7513
8131
  @for String
@@ -7517,7 +8135,7 @@ if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.String) {
7517
8135
  };
7518
8136
 
7519
8137
  /**
7520
- See {{#crossLink "Ember.String/dasherize"}}{{/crossLink}}
8138
+ See `Ember.String.dasherize`.
7521
8139
 
7522
8140
  @method dasherize
7523
8141
  @for String
@@ -7527,7 +8145,7 @@ if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.String) {
7527
8145
  };
7528
8146
 
7529
8147
  /**
7530
- See {{#crossLink "Ember.String/underscore"}}{{/crossLink}}
8148
+ See `Ember.String.underscore`.
7531
8149
 
7532
8150
  @method underscore
7533
8151
  @for String
@@ -7537,7 +8155,7 @@ if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.String) {
7537
8155
  };
7538
8156
 
7539
8157
  /**
7540
- See {{#crossLink "Ember.String/classify"}}{{/crossLink}}
8158
+ See `Ember.String.classify`.
7541
8159
 
7542
8160
  @method classify
7543
8161
  @for String
@@ -7547,7 +8165,7 @@ if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.String) {
7547
8165
  };
7548
8166
 
7549
8167
  /**
7550
- See {{#crossLink "Ember.String/capitalize"}}{{/crossLink}}
8168
+ See `Ember.String.capitalize`.
7551
8169
 
7552
8170
  @method capitalize
7553
8171
  @for String
@@ -7623,8 +8241,7 @@ if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Function) {
7623
8241
  will instead clear the cache so that it is updated when the next `get`
7624
8242
  is called on the property.
7625
8243
 
7626
- See {{#crossLink "Ember.ComputedProperty"}}{{/crossLink}},
7627
- {{#crossLink "Ember/computed"}}{{/crossLink}}
8244
+ See `Ember.ComputedProperty`, `Ember.computed`.
7628
8245
 
7629
8246
  @method property
7630
8247
  @for Function
@@ -7651,7 +8268,7 @@ if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Function) {
7651
8268
  });
7652
8269
  ```
7653
8270
 
7654
- See {{#crossLink "Ember.Observable/observes"}}{{/crossLink}}
8271
+ See `Ember.Observable.observes`.
7655
8272
 
7656
8273
  @method observes
7657
8274
  @for Function
@@ -7678,7 +8295,7 @@ if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Function) {
7678
8295
  });
7679
8296
  ```
7680
8297
 
7681
- See {{#crossLink "Ember.Observable/observesBefore"}}{{/crossLink}}
8298
+ See `Ember.Observable.observesBefore`.
7682
8299
 
7683
8300
  @method observesBefore
7684
8301
  @for Function
@@ -8575,9 +9192,7 @@ Ember.Enumerable = Ember.Mixin.create({
8575
9192
  // HELPERS
8576
9193
  //
8577
9194
 
8578
- var get = Ember.get, set = Ember.set, map = Ember.EnumerableUtils.map, cacheFor = Ember.cacheFor;
8579
-
8580
- function none(obj) { return obj===null || obj===undefined; }
9195
+ var get = Ember.get, set = Ember.set, isNone = Ember.isNone, map = Ember.EnumerableUtils.map, cacheFor = Ember.cacheFor;
8581
9196
 
8582
9197
  // ..........................................................
8583
9198
  // ARRAY
@@ -8600,7 +9215,7 @@ function none(obj) { return obj===null || obj===undefined; }
8600
9215
 
8601
9216
  You can use the methods defined in this module to access and modify array
8602
9217
  contents in a KVO-friendly way. You can also be notified whenever the
8603
- membership if an array changes by changing the syntax of the property to
9218
+ membership of an array changes by changing the syntax of the property to
8604
9219
  `.observes('*myProperty.[]')`.
8605
9220
 
8606
9221
  To support `Ember.Array` in your own class, you must override two
@@ -8617,9 +9232,6 @@ function none(obj) { return obj===null || obj===undefined; }
8617
9232
  */
8618
9233
  Ember.Array = Ember.Mixin.create(Ember.Enumerable, /** @scope Ember.Array.prototype */ {
8619
9234
 
8620
- // compatibility
8621
- isSCArray: true,
8622
-
8623
9235
  /**
8624
9236
  Your array must support the `length` property. Your replace methods should
8625
9237
  set this property whenever it changes.
@@ -8727,8 +9339,8 @@ Ember.Array = Ember.Mixin.create(Ember.Enumerable, /** @scope Ember.Array.protot
8727
9339
  slice: function(beginIndex, endIndex) {
8728
9340
  var ret = Ember.A([]);
8729
9341
  var length = get(this, 'length') ;
8730
- if (none(beginIndex)) beginIndex = 0 ;
8731
- if (none(endIndex) || (endIndex > length)) endIndex = length ;
9342
+ if (isNone(beginIndex)) beginIndex = 0 ;
9343
+ if (isNone(endIndex) || (endIndex > length)) endIndex = length ;
8732
9344
 
8733
9345
  if (beginIndex < 0) beginIndex = length + beginIndex;
8734
9346
  if (endIndex < 0) endIndex = length + endIndex;
@@ -8888,7 +9500,7 @@ Ember.Array = Ember.Mixin.create(Ember.Enumerable, /** @scope Ember.Array.protot
8888
9500
  @param {Number} startIdx The starting index in the array that will change.
8889
9501
  @param {Number} removeAmt The number of items that will be removed. If you
8890
9502
  pass `null` assumes 0
8891
- @param {Number} addAmt The number of items that will be added If you
9503
+ @param {Number} addAmt The number of items that will be added. If you
8892
9504
  pass `null` assumes 0.
8893
9505
  @return {Ember.Array} receiver
8894
9506
  */
@@ -8922,6 +9534,20 @@ Ember.Array = Ember.Mixin.create(Ember.Enumerable, /** @scope Ember.Array.protot
8922
9534
  return this;
8923
9535
  },
8924
9536
 
9537
+ /**
9538
+ If you are implementing an object that supports `Ember.Array`, call this
9539
+ method just after the array content changes to notify any observers and
9540
+ invalidate any related properties. Pass the starting index of the change
9541
+ as well as a delta of the amounts to change.
9542
+
9543
+ @method arrayContentDidChange
9544
+ @param {Number} startIdx The starting index in the array that did change.
9545
+ @param {Number} removeAmt The number of items that were removed. If you
9546
+ pass `null` assumes 0
9547
+ @param {Number} addAmt The number of items that were added. If you
9548
+ pass `null` assumes 0.
9549
+ @return {Ember.Array} receiver
9550
+ */
8925
9551
  arrayContentDidChange: function(startIdx, removeAmt, addAmt) {
8926
9552
 
8927
9553
  // if no args are passed assume everything changes
@@ -9062,8 +9688,7 @@ var get = Ember.get, set = Ember.set;
9062
9688
  @extends Ember.Mixin
9063
9689
  @since Ember 0.9
9064
9690
  */
9065
- Ember.Copyable = Ember.Mixin.create(
9066
- /** @scope Ember.Copyable.prototype */ {
9691
+ Ember.Copyable = Ember.Mixin.create(/** @scope Ember.Copyable.prototype */ {
9067
9692
 
9068
9693
  /**
9069
9694
  Override to return a copy of the receiver. Default implementation raises
@@ -9168,8 +9793,7 @@ var get = Ember.get, set = Ember.set;
9168
9793
  @extends Ember.Mixin
9169
9794
  @since Ember 0.9
9170
9795
  */
9171
- Ember.Freezable = Ember.Mixin.create(
9172
- /** @scope Ember.Freezable.prototype */ {
9796
+ Ember.Freezable = Ember.Mixin.create(/** @scope Ember.Freezable.prototype */ {
9173
9797
 
9174
9798
  /**
9175
9799
  Set to `true` when the object is frozen. Use this property to detect
@@ -9350,8 +9974,7 @@ var get = Ember.get, set = Ember.set;
9350
9974
  @uses Ember.Array
9351
9975
  @uses Ember.MutableEnumerable
9352
9976
  */
9353
- Ember.MutableArray = Ember.Mixin.create(Ember.Array, Ember.MutableEnumerable,
9354
- /** @scope Ember.MutableArray.prototype */ {
9977
+ Ember.MutableArray = Ember.Mixin.create(Ember.Array, Ember.MutableEnumerable,/** @scope Ember.MutableArray.prototype */ {
9355
9978
 
9356
9979
  /**
9357
9980
  __Required.__ You must implement this method to apply this mixin.
@@ -9622,7 +10245,6 @@ Ember.MutableArray = Ember.Mixin.create(Ember.Array, Ember.MutableEnumerable,
9622
10245
 
9623
10246
  });
9624
10247
 
9625
-
9626
10248
  })();
9627
10249
 
9628
10250
 
@@ -9670,7 +10292,7 @@ var get = Ember.get, set = Ember.set;
9670
10292
  For example:
9671
10293
 
9672
10294
  ```javascript
9673
- Ember.Object.create({
10295
+ Ember.Object.extend({
9674
10296
  valueObserver: function() {
9675
10297
  // Executes whenever the "value" property changes
9676
10298
  }.observes('value')
@@ -9689,8 +10311,8 @@ var get = Ember.get, set = Ember.set;
9689
10311
  object.addObserver('propertyKey', targetObject, targetAction)
9690
10312
  ```
9691
10313
 
9692
- This will call the `targetAction` method on the `targetObject` to be called
9693
- whenever the value of the `propertyKey` changes.
10314
+ This will call the `targetAction` method on the `targetObject` whenever
10315
+ the value of the `propertyKey` changes.
9694
10316
 
9695
10317
  Note that if `propertyKey` is a computed property, the observer will be
9696
10318
  called when any of the property dependencies are changed, even if the
@@ -9950,8 +10572,8 @@ Ember.Observable = Ember.Mixin.create(/** @scope Ember.Observable.prototype */ {
9950
10572
 
9951
10573
  This is the core method used to register an observer for a property.
9952
10574
 
9953
- Once you call this method, anytime the key's value is set, your observer
9954
- will be notified. Note that the observers are triggered anytime the
10575
+ Once you call this method, any time the key's value is set, your observer
10576
+ will be notified. Note that the observers are triggered any time the
9955
10577
  value is set, regardless of whether it has actually changed. Your
9956
10578
  observer should be prepared to handle that.
9957
10579
 
@@ -10076,11 +10698,11 @@ Ember.Observable = Ember.Mixin.create(/** @scope Ember.Observable.prototype */ {
10076
10698
 
10077
10699
  @method incrementProperty
10078
10700
  @param {String} keyName The name of the property to increment
10079
- @param {Object} increment The amount to increment by. Defaults to 1
10080
- @return {Object} The new property value
10701
+ @param {Number} increment The amount to increment by. Defaults to 1
10702
+ @return {Number} The new property value
10081
10703
  */
10082
10704
  incrementProperty: function(keyName, increment) {
10083
- if (!increment) { increment = 1; }
10705
+ if (Ember.isNone(increment)) { increment = 1; }
10084
10706
  set(this, keyName, (get(this, keyName) || 0)+increment);
10085
10707
  return get(this, keyName);
10086
10708
  },
@@ -10095,12 +10717,12 @@ Ember.Observable = Ember.Mixin.create(/** @scope Ember.Observable.prototype */ {
10095
10717
 
10096
10718
  @method decrementProperty
10097
10719
  @param {String} keyName The name of the property to decrement
10098
- @param {Object} increment The amount to decrement by. Defaults to 1
10099
- @return {Object} The new property value
10720
+ @param {Number} decrement The amount to decrement by. Defaults to 1
10721
+ @return {Number} The new property value
10100
10722
  */
10101
- decrementProperty: function(keyName, increment) {
10102
- if (!increment) { increment = 1; }
10103
- set(this, keyName, (get(this, keyName) || 0)-increment);
10723
+ decrementProperty: function(keyName, decrement) {
10724
+ if (Ember.isNone(decrement)) { decrement = 1; }
10725
+ set(this, keyName, (get(this, keyName) || 0)-decrement);
10104
10726
  return get(this, keyName);
10105
10727
  },
10106
10728
 
@@ -10109,7 +10731,7 @@ Ember.Observable = Ember.Mixin.create(/** @scope Ember.Observable.prototype */ {
10109
10731
  current value.
10110
10732
 
10111
10733
  ```javascript
10112
- starship.toggleProperty('warpDriveEnaged');
10734
+ starship.toggleProperty('warpDriveEngaged');
10113
10735
  ```
10114
10736
 
10115
10737
  @method toggleProperty
@@ -10141,7 +10763,6 @@ Ember.Observable = Ember.Mixin.create(/** @scope Ember.Observable.prototype */ {
10141
10763
  }
10142
10764
  });
10143
10765
 
10144
-
10145
10766
  })();
10146
10767
 
10147
10768
 
@@ -10436,9 +11057,9 @@ Ember.Evented = Ember.Mixin.create({
10436
11057
  (function() {
10437
11058
  var RSVP = requireModule("rsvp");
10438
11059
 
10439
- RSVP.async = function(callback, binding) {
11060
+ RSVP.configure('async', function(callback, binding) {
10440
11061
  Ember.run.schedule('actions', binding, callback);
10441
- };
11062
+ });
10442
11063
 
10443
11064
  /**
10444
11065
  @module ember
@@ -10460,9 +11081,22 @@ Ember.DeferredMixin = Ember.Mixin.create({
10460
11081
  @param {Function} doneCallback a callback function to be called when done
10461
11082
  @param {Function} failCallback a callback function to be called when failed
10462
11083
  */
10463
- then: function(doneCallback, failCallback) {
10464
- var promise = get(this, 'promise');
10465
- return promise.then.apply(promise, arguments);
11084
+ then: function(resolve, reject) {
11085
+ var deferred, promise, entity;
11086
+
11087
+ entity = this;
11088
+ deferred = get(this, '_deferred');
11089
+ promise = deferred.promise;
11090
+
11091
+ function fulfillmentHandler(fulfillment) {
11092
+ if (fulfillment === promise) {
11093
+ return resolve(entity);
11094
+ } else {
11095
+ return resolve(fulfillment);
11096
+ }
11097
+ }
11098
+
11099
+ return promise.then(resolve && fulfillmentHandler, reject);
10466
11100
  },
10467
11101
 
10468
11102
  /**
@@ -10471,7 +11105,16 @@ Ember.DeferredMixin = Ember.Mixin.create({
10471
11105
  @method resolve
10472
11106
  */
10473
11107
  resolve: function(value) {
10474
- get(this, 'promise').resolve(value);
11108
+ var deferred, promise;
11109
+
11110
+ deferred = get(this, '_deferred');
11111
+ promise = deferred.promise;
11112
+
11113
+ if (value === this){
11114
+ deferred.resolve(promise);
11115
+ } else {
11116
+ deferred.resolve(value);
11117
+ }
10475
11118
  },
10476
11119
 
10477
11120
  /**
@@ -10480,11 +11123,11 @@ Ember.DeferredMixin = Ember.Mixin.create({
10480
11123
  @method reject
10481
11124
  */
10482
11125
  reject: function(value) {
10483
- get(this, 'promise').reject(value);
11126
+ get(this, '_deferred').reject(value);
10484
11127
  },
10485
11128
 
10486
- promise: Ember.computed(function() {
10487
- return new RSVP.Promise();
11129
+ _deferred: Ember.computed(function() {
11130
+ return RSVP.defer();
10488
11131
  })
10489
11132
  });
10490
11133
 
@@ -10797,21 +11440,23 @@ CoreObject.PrototypeMixin = Mixin.create({
10797
11440
  raised.
10798
11441
 
10799
11442
  Note that destruction is scheduled for the end of the run loop and does not
10800
- happen immediately.
11443
+ happen immediately. It will set an isDestroying flag immediately.
10801
11444
 
10802
11445
  @method destroy
10803
11446
  @return {Ember.Object} receiver
10804
11447
  */
10805
11448
  destroy: function() {
10806
- if (this._didCallDestroy) { return; }
10807
-
11449
+ if (this.isDestroying) { return; }
10808
11450
  this.isDestroying = true;
10809
- this._didCallDestroy = true;
10810
11451
 
11452
+ schedule('actions', this, this.willDestroy);
10811
11453
  schedule('destroy', this, this._scheduledDestroy);
10812
11454
  return this;
10813
11455
  },
10814
11456
 
11457
+ /**
11458
+ Override to implement teardown.
11459
+ */
10815
11460
  willDestroy: Ember.K,
10816
11461
 
10817
11462
  /**
@@ -10823,10 +11468,9 @@ CoreObject.PrototypeMixin = Mixin.create({
10823
11468
  @method _scheduledDestroy
10824
11469
  */
10825
11470
  _scheduledDestroy: function() {
10826
- if (this.willDestroy) { this.willDestroy(); }
11471
+ if (this.isDestroyed) { return; }
10827
11472
  destroy(this);
10828
11473
  this.isDestroyed = true;
10829
- if (this.didDestroy) { this.didDestroy(); }
10830
11474
  },
10831
11475
 
10832
11476
  bind: function(to, from) {
@@ -11317,8 +11961,7 @@ var get = Ember.get, set = Ember.set;
11317
11961
  @extends Ember.Object
11318
11962
  @uses Ember.MutableArray
11319
11963
  */
11320
- Ember.ArrayProxy = Ember.Object.extend(Ember.MutableArray,
11321
- /** @scope Ember.ArrayProxy.prototype */ {
11964
+ Ember.ArrayProxy = Ember.Object.extend(Ember.MutableArray,/** @scope Ember.ArrayProxy.prototype */ {
11322
11965
 
11323
11966
  /**
11324
11967
  The content array. Must be an object that implements `Ember.Array` and/or
@@ -11594,7 +12237,6 @@ Ember.ArrayProxy = Ember.Object.extend(Ember.MutableArray,
11594
12237
  }
11595
12238
  });
11596
12239
 
11597
-
11598
12240
  })();
11599
12241
 
11600
12242
 
@@ -11694,8 +12336,7 @@ function contentPropertyDidChange(content, contentKey) {
11694
12336
  @namespace Ember
11695
12337
  @extends Ember.Object
11696
12338
  */
11697
- Ember.ObjectProxy = Ember.Object.extend(
11698
- /** @scope Ember.ObjectProxy.prototype */ {
12339
+ Ember.ObjectProxy = Ember.Object.extend(/** @scope Ember.ObjectProxy.prototype */ {
11699
12340
  /**
11700
12341
  The object whose properties will be forwarded.
11701
12342
 
@@ -12133,7 +12774,7 @@ if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Array) {
12133
12774
  @submodule ember-runtime
12134
12775
  */
12135
12776
 
12136
- var get = Ember.get, set = Ember.set, guidFor = Ember.guidFor, none = Ember.isNone, fmt = Ember.String.fmt;
12777
+ var get = Ember.get, set = Ember.set, guidFor = Ember.guidFor, isNone = Ember.isNone, fmt = Ember.String.fmt;
12137
12778
 
12138
12779
  /**
12139
12780
  An unordered collection of objects.
@@ -12491,7 +13132,7 @@ Ember.Set = Ember.CoreObject.extend(Ember.MutableEnumerable, Ember.Copyable, Emb
12491
13132
  // implements Ember.MutableEnumerable
12492
13133
  addObject: function(obj) {
12493
13134
  if (get(this, 'isFrozen')) throw new Error(Ember.FROZEN_ERROR);
12494
- if (none(obj)) return this; // nothing to do
13135
+ if (isNone(obj)) return this; // nothing to do
12495
13136
 
12496
13137
  var guid = guidFor(obj),
12497
13138
  idx = this[guid],
@@ -12519,7 +13160,7 @@ Ember.Set = Ember.CoreObject.extend(Ember.MutableEnumerable, Ember.Copyable, Emb
12519
13160
  // implements Ember.MutableEnumerable
12520
13161
  removeObject: function(obj) {
12521
13162
  if (get(this, 'isFrozen')) throw new Error(Ember.FROZEN_ERROR);
12522
- if (none(obj)) return this; // nothing to do
13163
+ if (isNone(obj)) return this; // nothing to do
12523
13164
 
12524
13165
  var guid = guidFor(obj),
12525
13166
  idx = this[guid],
@@ -12594,7 +13235,7 @@ Deferred.reopenClass({
12594
13235
  promise: function(callback, binding) {
12595
13236
  var deferred = Deferred.create();
12596
13237
  callback.call(binding, deferred);
12597
- return get(deferred, 'promise');
13238
+ return deferred;
12598
13239
  }
12599
13240
  });
12600
13241
 
@@ -12605,6 +13246,8 @@ Ember.Deferred = Deferred;
12605
13246
 
12606
13247
 
12607
13248
  (function() {
13249
+ var forEach = Ember.ArrayPolyfills.forEach;
13250
+
12608
13251
  /**
12609
13252
  @module ember
12610
13253
  @submodule ember-runtime
@@ -12637,12 +13280,10 @@ Ember.onLoad = function(name, callback) {
12637
13280
  @param object {Object} object to pass to callbacks
12638
13281
  */
12639
13282
  Ember.runLoadHooks = function(name, object) {
12640
- var hooks;
12641
-
12642
13283
  loaded[name] = object;
12643
13284
 
12644
- if (hooks = loadHooks[name]) {
12645
- loadHooks[name].forEach(function(callback) {
13285
+ if (loadHooks[name]) {
13286
+ forEach.call(loadHooks[name], function(callback) {
12646
13287
  callback(object);
12647
13288
  });
12648
13289
  }
@@ -12716,6 +13357,8 @@ Ember.ControllerMixin = Ember.Mixin.create({
12716
13357
 
12717
13358
  container: null,
12718
13359
 
13360
+ parentController: null,
13361
+
12719
13362
  store: null,
12720
13363
 
12721
13364
  model: Ember.computed.alias('content'),
@@ -13058,6 +13701,10 @@ var get = Ember.get, set = Ember.set, forEach = Ember.EnumerableUtils.forEach,
13058
13701
  });
13059
13702
  ```
13060
13703
 
13704
+ The itemController instances will have a `parentController` property set to
13705
+ either the the `parentController` property of the `ArrayController`
13706
+ or to the `ArrayController` instance itself.
13707
+
13061
13708
  @class ArrayController
13062
13709
  @namespace Ember
13063
13710
  @extends Ember.ArrayProxy
@@ -13168,6 +13815,7 @@ Ember.ArrayController = Ember.ArrayProxy.extend(Ember.ControllerMixin,
13168
13815
  }
13169
13816
 
13170
13817
  subController.set('target', this);
13818
+ subController.set('parentController', get(this, 'parentController') || this);
13171
13819
  subController.set('content', object);
13172
13820
 
13173
13821
  return subController;