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.

@@ -1,7 +1,7 @@
1
1
  (function() {
2
2
  var Ember = { assert: function() {} };
3
- // Version: v1.0.0-rc.3-2-g85bfdbf
4
- // Last commit: 85bfdbf (2013-07-25 20:16:20 -0400)
3
+ // Version: v1.0.0-rc4
4
+ // Last commit: ae2e55f (2013-05-27 19:34:11 -0400)
5
5
 
6
6
 
7
7
  (function() {
@@ -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.
1732
+ @private
1747
1733
 
1748
- Internally, a Map has two data structures:
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.
1749
1738
 
1750
- 1. `keys`: an OrderedSet of all of the existing keys
1751
- 2. `values`: a JavaScript Object indexed by the `Ember.guidFor(key)`
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.
1744
+ */
1745
+ Ember.normalizeTuple = function(target, path) {
1746
+ return normalizeTuple(target, path);
1747
+ };
1752
1748
 
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`.
1749
+ Ember.getWithDefault = function(root, key, defaultValue) {
1750
+ var value = get(root, key);
1757
1751
 
1758
- @class Map
1759
- @namespace Ember
1760
- @private
1761
- @constructor
1762
- */
1763
- var Map = Ember.Map = function() {
1764
- this.keys = Ember.OrderedSet.create();
1765
- this.values = {};
1752
+ if (value === undefined) { return defaultValue; }
1753
+ return value;
1766
1754
  };
1767
1755
 
1756
+
1757
+ Ember.get = get;
1758
+ Ember.getPath = Ember.deprecateFunc('getPath is deprecated since get now supports paths', Ember.get);
1759
+
1760
+ })();
1761
+
1762
+
1763
+
1764
+ (function() {
1768
1765
  /**
1769
- @method create
1770
- @static
1766
+ @module ember-metal
1771
1767
  */
1772
- Map.create = function() {
1773
- return new Map();
1774
- };
1775
1768
 
1776
- Map.prototype = {
1777
- /**
1778
- Retrieve the value associated with a given 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;
1779
1774
 
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);
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.
1787
1779
 
1788
- return values[guid];
1789
- },
1780
+ The hashes are stored in the object's meta hash, and look like this:
1790
1781
 
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.
1782
+ // Object's meta hash
1783
+ {
1784
+ listeners: { // variable name: `listenerSet`
1785
+ "foo:changed": [ // variable name: `actions`
1786
+ [target, method, flags]
1787
+ ]
1788
+ }
1789
+ }
1794
1790
 
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);
1791
+ */
1803
1792
 
1804
- keys.add(key);
1805
- values[guid] = value;
1806
- },
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
+ }
1807
1800
 
1808
- /**
1809
- Removes a value from the map for an associated key.
1801
+ function actionsFor(obj, eventName) {
1802
+ var meta = metaFor(obj, true),
1803
+ actions;
1810
1804
 
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);
1805
+ if (!meta.listeners) { meta.listeners = {}; }
1821
1806
 
1822
- if (values.hasOwnProperty(guid)) {
1823
- keys.remove(key);
1824
- delete values[guid];
1825
- return true;
1826
- } else {
1827
- return false;
1828
- }
1829
- },
1807
+ if (!meta.hasOwnProperty('listeners')) {
1808
+ // setup inherited copy of the listeners object
1809
+ meta.listeners = o_create(meta.listeners);
1810
+ }
1830
1811
 
1831
- /**
1832
- Check whether a key is present.
1812
+ actions = meta.listeners[eventName];
1833
1813
 
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);
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] = [];
1819
+ }
1841
1820
 
1842
- return values.hasOwnProperty(guid);
1843
- },
1821
+ return actions;
1822
+ }
1844
1823
 
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.
1824
+ function actionsUnion(obj, eventName, otherActions) {
1825
+ var meta = obj[META_KEY],
1826
+ actions = meta && meta.listeners && meta.listeners[eventName];
1848
1827
 
1849
- The keys are guaranteed to be iterated over in insertion order.
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);
1850
1834
 
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;
1835
+ if (actionIndex === -1) {
1836
+ otherActions.push([target, method, flags]);
1837
+ }
1838
+ }
1839
+ }
1859
1840
 
1860
- keys.forEach(function(key) {
1861
- var guid = guidFor(key);
1862
- callback.call(self, key, values[guid]);
1863
- });
1864
- },
1841
+ function actionsDiff(obj, eventName, otherActions) {
1842
+ var meta = obj[META_KEY],
1843
+ actions = meta && meta.listeners && meta.listeners[eventName],
1844
+ diffActions = [];
1865
1845
 
1866
- /**
1867
- @method copy
1868
- @return {Ember.Map}
1869
- */
1870
- copy: function() {
1871
- return copyMap(this, new Map());
1872
- }
1873
- };
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);
1874
1852
 
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
- };
1853
+ if (actionIndex !== -1) { continue; }
1888
1854
 
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();
1855
+ otherActions.push([target, method, flags]);
1856
+ diffActions.push([target, method, flags]);
1902
1857
  }
1903
- };
1904
1858
 
1905
- MapWithDefault.prototype = Ember.create(Map.prototype);
1859
+ return diffActions;
1860
+ }
1906
1861
 
1907
1862
  /**
1908
- Retrieve the value associated with a given key.
1863
+ Add an event listener
1909
1864
 
1910
- @method get
1911
- @param {*} key
1912
- @return {*} the value associated with the key, or the default value
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
1913
1872
  */
1914
- MapWithDefault.prototype.get = function(key) {
1915
- var hasValue = this.has(key);
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);
1916
1875
 
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;
1876
+ if (!method && 'function' === typeof target) {
1877
+ method = target;
1878
+ target = null;
1923
1879
  }
1924
- };
1925
1880
 
1926
- /**
1927
- @method copy
1928
- @return {Ember.MapWithDefault}
1929
- */
1930
- MapWithDefault.prototype.copy = function() {
1931
- return copyMap(this, new MapWithDefault({
1932
- defaultValue: this.defaultValue
1933
- }));
1934
- };
1881
+ var actions = actionsFor(obj, eventName),
1882
+ actionIndex = indexOf(actions, target, method),
1883
+ flags = 0;
1935
1884
 
1936
- })();
1885
+ if (once) flags |= ONCE;
1937
1886
 
1887
+ if (actionIndex !== -1) { return; }
1938
1888
 
1889
+ actions.push([target, method, flags]);
1939
1890
 
1940
- (function() {
1941
- /**
1942
- @module ember-metal
1943
- */
1944
-
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 = /^([^\.\*]+)/;
1952
-
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
  }
@@ -4443,209 +4502,533 @@ Ember._suspendBeforeObservers = function(obj, paths, target, method, callback) {
4443
4502
  return Ember._suspendListeners(obj, events, target, method, callback);
4444
4503
  };
4445
4504
 
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
- };
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
+ },
4622
+
4623
+ defer: function(queueName, target, method /* , args */) {
4624
+ if (!method) {
4625
+ method = target;
4626
+ target = null;
4627
+ }
4628
+
4629
+ if (typeof method === 'string') {
4630
+ method = target[method];
4631
+ }
4632
+
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
+ },
4638
+
4639
+ deferOnce: function(queueName, target, method /* , args */) {
4640
+ if (!method) {
4641
+ method = target;
4642
+ target = null;
4643
+ }
4644
+
4645
+ if (typeof method === 'string') {
4646
+ method = target[method];
4647
+ }
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
+ },
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;
4661
+
4662
+ if (!method) {
4663
+ method = target;
4664
+ target = null;
4665
+ }
4666
+
4667
+ if (typeof method === 'string') {
4668
+ method = target[method];
4669
+ }
4670
+
4671
+ var fn, args;
4672
+ if (arguments.length > 2) {
4673
+ args = slice.call(arguments, 2);
4674
+
4675
+ fn = function() {
4676
+ method.apply(target, args);
4677
+ };
4678
+ } else {
4679
+ fn = function() {
4680
+ method.call(target);
4681
+ };
4682
+ }
4683
+
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
+ }
4689
+
4690
+ timers.splice(i, 0, executeAt, fn);
4450
4691
 
4451
- Ember.beforeObserversFor = function(obj, path) {
4452
- return Ember.listenersFor(obj, beforeEvent(path));
4453
- };
4692
+ if (laterTimer && laterTimerExpiresAt < executeAt) { return fn; }
4454
4693
 
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
- })();
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
+ },
4468
4707
 
4708
+ debounce: function(target, method /* , args, wait */) {
4709
+ var self = this,
4710
+ args = arguments,
4711
+ wait = pop.call(args),
4712
+ debouncee;
4469
4713
 
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
+ }
4470
4718
 
4471
- (function() {
4472
- // Ember.Logger
4473
- // Ember.watch.flushPending
4474
- // Ember.beginPropertyChanges, Ember.endPropertyChanges
4475
- // Ember.guidFor, Ember.tryFinally
4719
+ var timer = setTimeout(function() {
4720
+ self.run.apply(self, args);
4476
4721
 
4477
- /**
4478
- @module ember-metal
4479
- */
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
+ }
4480
4731
 
4481
- // ..........................................................
4482
- // HELPERS
4483
- //
4732
+ if (index > -1) { debouncees.splice(index, 1); }
4733
+ }, wait);
4484
4734
 
4485
- var slice = [].slice,
4486
- forEach = Ember.ArrayPolyfills.forEach;
4735
+ debouncees.push([target, method, timer]);
4736
+ },
4487
4737
 
4488
- // invokes passed params - normalizing so you can pass target/func,
4489
- // target/string or just func
4490
- function invoke(target, method, args, ignore) {
4738
+ cancelTimers: function() {
4739
+ for (var i = 0, l = debouncees.length; i < l; i++) {
4740
+ clearTimeout(debouncees[i][2]);
4741
+ }
4742
+ debouncees = [];
4491
4743
 
4492
- if (method === undefined) {
4493
- method = target;
4494
- target = undefined;
4495
- }
4744
+ if (laterTimer) {
4745
+ clearTimeout(laterTimer);
4746
+ laterTimer = null;
4747
+ }
4748
+ timers = [];
4496
4749
 
4497
- if ('string' === typeof method) { method = target[method]; }
4498
- if (args && ignore > 0) {
4499
- args = args.length > ignore ? slice.call(args, ignore) : null;
4500
- }
4750
+ if (autorun) {
4751
+ clearTimeout(autorun);
4752
+ autorun = null;
4753
+ }
4754
+ },
4501
4755
 
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
- }
4756
+ hasTimers: function() {
4757
+ return !!timers.length || autorun;
4758
+ },
4507
4759
 
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
+ };
4508
4773
 
4509
- // ..........................................................
4510
- // RUNLOOP
4511
- //
4774
+ Backburner.prototype.schedule = Backburner.prototype.defer;
4775
+ Backburner.prototype.scheduleOnce = Backburner.prototype.deferOnce;
4776
+ Backburner.prototype.later = Backburner.prototype.setTimeout;
4512
4777
 
4513
- /**
4514
- Ember RunLoop (Private)
4778
+ function createAutorun(backburner) {
4779
+ backburner.begin();
4780
+ autorun = setTimeout(function() {
4781
+ backburner.end();
4782
+ autorun = null;
4783
+ });
4784
+ }
4515
4785
 
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
- };
4786
+ function executeTimers(self) {
4787
+ var now = +new Date(),
4788
+ time, fns, i, l;
4525
4789
 
4526
- RunLoop.prototype = {
4527
- /**
4528
- @method end
4529
- */
4530
- end: function() {
4531
- this.flush();
4532
- },
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
+ }
4533
4796
 
4534
- /**
4535
- @method prev
4536
- */
4537
- prev: function() {
4538
- return this._prev;
4539
- },
4797
+ fns = timers.splice(0, i);
4540
4798
 
4541
- // ..........................................................
4542
- // Delayed Actions
4543
- //
4799
+ for (i = 1, l = fns.length; i < l; i += 2) {
4800
+ self.schedule(self.options.defaultQueue, null, fns[i]);
4801
+ }
4802
+ });
4544
4803
 
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] = []; }
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
+ }
4812
+ }
4556
4813
 
4557
- var args = arguments.length > 3 ? slice.call(arguments, 3) : null;
4558
- queue.push({ target: target, method: method, args: args });
4559
- return this;
4560
- },
4561
4814
 
4562
- /**
4563
- @method flush
4564
- @param {String} queueName
4565
- */
4566
- flush: function(queueName) {
4567
- var queueNames, idx, len, queue, log;
4815
+ __exports__.Backburner = Backburner;
4816
+ });
4568
4817
 
4569
- if (!this._queues) { return this; } // nothing to do
4818
+ define("backburner/deferred_action_queues",
4819
+ ["backburner/queue","exports"],
4820
+ function(__dependency1__, __exports__) {
4821
+ "use strict";
4822
+ var Queue = __dependency1__.Queue;
4570
4823
 
4571
- function iter(item) {
4572
- invoke(item.target, item.method, item.args);
4573
- }
4824
+ function DeferredActionQueues(queueNames, options) {
4825
+ var queues = this.queues = {};
4826
+ this.queueNames = queueNames = queueNames || [];
4574
4827
 
4575
- function tryable() {
4576
- forEach.call(queue, iter);
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
+ }
4577
4833
  }
4578
4834
 
4579
- Ember.watch.flushPending(); // make sure all chained watchers are setup
4835
+ DeferredActionQueues.prototype = {
4836
+ queueNames: null,
4837
+ queues: null,
4580
4838
 
4581
- if (queueName) {
4582
- while (this._queues && (queue = this._queues[queueName])) {
4583
- this._queues[queueName] = null;
4839
+ schedule: function(queueName, target, method, args, onceFlag, stack) {
4840
+ var queues = this.queues,
4841
+ queue = queues[queueName];
4584
4842
 
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'); }
4843
+ if (!queue) { throw new Error("You attempted to schedule an action in a queue (" + queueName + ") that doesn't exist"); }
4590
4844
 
4591
- Ember.beginPropertyChanges();
4845
+ if (onceFlag) {
4846
+ return queue.pushUnique(target, method, args, stack);
4847
+ } else {
4848
+ return queue.push(target, method, args, stack);
4849
+ }
4850
+ },
4592
4851
 
4593
- Ember.tryFinally(tryable, Ember.endPropertyChanges);
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
+ }
4594
4886
 
4595
- if (log) { Ember.Logger.log('End: Flush Sync Queue'); }
4887
+ queueIndex += 4;
4888
+ }
4889
+ if (numberOfQueueItems && after) { after(); }
4596
4890
 
4597
- } else {
4598
- forEach.call(queue, iter);
4891
+ if ((priorQueueNameIndex = indexOfPriorQueueWithActions(this, queueNameIndex)) !== -1) {
4892
+ queueNameIndex = priorQueueNameIndex;
4893
+ continue outerloop;
4894
+ }
4895
+
4896
+ queueNameIndex++;
4599
4897
  }
4600
4898
  }
4899
+ };
4900
+
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
+ }
4601
4909
 
4602
- } else {
4603
- queueNames = Ember.run.queues;
4604
- len = queueNames.length;
4605
- idx = 0;
4910
+ return -1;
4911
+ }
4606
4912
 
4607
- outerloop:
4608
- while (idx < len) {
4609
- queueName = queueNames[idx];
4610
- queue = this._queues && this._queues[queueName];
4611
- delete this._queues[queueName];
4913
+ __exports__.DeferredActionQueues = DeferredActionQueues;
4914
+ });
4612
4915
 
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'); }
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
+ },
4619
4938
 
4620
- Ember.beginPropertyChanges();
4939
+ pushUnique: function(target, method, args, stack) {
4940
+ var queue = this._queue, currentTarget, currentMethod, i, l;
4621
4941
 
4622
- Ember.tryFinally(tryable, Ember.endPropertyChanges);
4942
+ for (i = 0, l = queue.length; i < l; i += 4) {
4943
+ currentTarget = queue[i];
4944
+ currentMethod = queue[i+1];
4623
4945
 
4624
- if (log) { Ember.Logger.log('End: Flush Sync Queue'); }
4625
- } else {
4626
- forEach.call(queue, iter);
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
4627
4950
  }
4628
4951
  }
4629
4952
 
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;
4953
+ this._queue.push(target, method, args, stack);
4954
+ return {queue: this, target: target, method: method};
4955
+ },
4956
+
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);
4975
+ } else {
4976
+ method.call(target);
4636
4977
  }
4637
4978
  }
4979
+ if (l && after) { after(); }
4980
+
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;
4987
+ }
4988
+ },
4989
+
4990
+ cancel: function(actionToCancel) {
4991
+ var queue = this._queue, currentTarget, currentMethod, i, l;
4992
+
4993
+ for (i = 0, l = queue.length; i < l; i += 4) {
4994
+ currentTarget = queue[i];
4995
+ currentMethod = queue[i+1];
4638
4996
 
4639
- idx++;
4997
+ if (currentTarget === actionToCancel.target && currentMethod === actionToCancel.method) {
4998
+ queue.splice(i, 4);
4999
+ return true;
5000
+ }
5001
+ }
4640
5002
  }
4641
- }
5003
+ };
4642
5004
 
4643
- return this;
4644
- }
5005
+ __exports__.Queue = Queue;
5006
+ });
5007
+
5008
+ })();
5009
+
5010
+
5011
+
5012
+ (function() {
5013
+ var onBegin = function(current) {
5014
+ Ember.run.currentRunLoop = current;
5015
+ };
4645
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
@@ -4914,77 +5275,12 @@ function invokeLaterTimers() {
4914
5275
  @param {Object} [args*] Optional arguments to pass to the timeout.
4915
5276
  @param {Number} wait Number of milliseconds to wait.
4916
5277
  @return {String} a string you can use to cancel the timer in
4917
- {{#crossLink "Ember/run.cancel"}}{{/crossLink}} later.
5278
+ `Ember.run.cancel` later.
4918
5279
  */
4919
5280
  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;
5281
+ return backburner.later.apply(backburner, arguments);
4951
5282
  };
4952
5283
 
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
- }
4984
-
4985
- return guid;
4986
- }
4987
-
4988
5284
  /**
4989
5285
  Schedule a function to run one time during the current RunLoop. This is equivalent
4990
5286
  to calling `scheduleOnce` with the "actions" queue.
@@ -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;
@@ -13241,7 +13889,7 @@ Ember Runtime
13241
13889
  */
13242
13890
 
13243
13891
  var jQuery = Ember.imports.jQuery;
13244
- Ember.assert("Ember Views require jQuery 1.8, 1.9 or 2.0", jQuery && (jQuery().jquery.match(/^((1\.(8|9))|2.0)(\.\d+)?(pre|rc\d?)?/) || Ember.ENV.FORCE_JQUERY));
13892
+ Ember.assert("Ember Views require jQuery 1.8, 1.9, 1.10, or 2.0", jQuery && (jQuery().jquery.match(/^((1\.(8|9|10))|2.0)(\.\d+)?(pre|rc\d?)?/) || Ember.ENV.FORCE_JQUERY));
13245
13893
 
13246
13894
  /**
13247
13895
  Alias for jQuery
@@ -13281,7 +13929,7 @@ if (Ember.$) {
13281
13929
  @submodule ember-views
13282
13930
  */
13283
13931
 
13284
- /*** BEGIN METAMORPH HELPERS ***/
13932
+ /* BEGIN METAMORPH HELPERS */
13285
13933
 
13286
13934
  // Internet Explorer prior to 9 does not allow setting innerHTML if the first element
13287
13935
  // is a "zero-scope" element. This problem can be worked around by making
@@ -13354,7 +14002,7 @@ var setInnerHTMLWithoutFix = function(element, html) {
13354
14002
  }
13355
14003
  };
13356
14004
 
13357
- /*** END METAMORPH HELPERS */
14005
+ /* END METAMORPH HELPERS */
13358
14006
 
13359
14007
 
13360
14008
  var innerHTMLTags = {};
@@ -13443,45 +14091,6 @@ ClassSet.prototype = {
13443
14091
  }
13444
14092
  };
13445
14093
 
13446
- var BAD_TAG_NAME_TEST_REGEXP = /[^a-zA-Z\-]/;
13447
- var BAD_TAG_NAME_REPLACE_REGEXP = /[^a-zA-Z\-]/g;
13448
-
13449
- function stripTagName(tagName) {
13450
- if (!tagName) {
13451
- return tagName;
13452
- }
13453
-
13454
- if (!BAD_TAG_NAME_TEST_REGEXP.test(tagName)) {
13455
- return tagName;
13456
- }
13457
-
13458
- return tagName.replace(BAD_TAG_NAME_REPLACE_REGEXP, '');
13459
- }
13460
-
13461
- var BAD_CHARS_REGEXP = /&(?!\w+;)|[<>"'`]/g;
13462
- var POSSIBLE_CHARS_REGEXP = /[&<>"'`]/;
13463
-
13464
- function escapeAttribute(value) {
13465
- // Stolen shamelessly from Handlebars
13466
-
13467
- var escape = {
13468
- "<": "&lt;",
13469
- ">": "&gt;",
13470
- '"': "&quot;",
13471
- "'": "&#x27;",
13472
- "`": "&#x60;"
13473
- };
13474
-
13475
- var escapeChar = function(chr) {
13476
- return escape[chr] || "&amp;";
13477
- };
13478
-
13479
- var string = value.toString();
13480
-
13481
- if(!POSSIBLE_CHARS_REGEXP.test(string)) { return string; }
13482
- return string.replace(BAD_CHARS_REGEXP, escapeChar);
13483
- }
13484
-
13485
14094
  /**
13486
14095
  `Ember.RenderBuffer` gathers information regarding the a view and generates the
13487
14096
  final representation. `Ember.RenderBuffer` will generate HTML which can be pushed
@@ -13769,14 +14378,14 @@ Ember._RenderBuffer.prototype =
13769
14378
  style = this.elementStyle,
13770
14379
  attr, prop;
13771
14380
 
13772
- buffer += '<' + stripTagName(tagName);
14381
+ buffer += '<' + tagName;
13773
14382
 
13774
14383
  if (id) {
13775
- buffer += ' id="' + escapeAttribute(id) + '"';
14384
+ buffer += ' id="' + this._escapeAttribute(id) + '"';
13776
14385
  this.elementId = null;
13777
14386
  }
13778
14387
  if (classes) {
13779
- buffer += ' class="' + escapeAttribute(classes.join(' ')) + '"';
14388
+ buffer += ' class="' + this._escapeAttribute(classes.join(' ')) + '"';
13780
14389
  this.classes = null;
13781
14390
  }
13782
14391
 
@@ -13785,7 +14394,7 @@ Ember._RenderBuffer.prototype =
13785
14394
 
13786
14395
  for (prop in style) {
13787
14396
  if (style.hasOwnProperty(prop)) {
13788
- buffer += prop + ':' + escapeAttribute(style[prop]) + ';';
14397
+ buffer += prop + ':' + this._escapeAttribute(style[prop]) + ';';
13789
14398
  }
13790
14399
  }
13791
14400
 
@@ -13797,7 +14406,7 @@ Ember._RenderBuffer.prototype =
13797
14406
  if (attrs) {
13798
14407
  for (attr in attrs) {
13799
14408
  if (attrs.hasOwnProperty(attr)) {
13800
- buffer += ' ' + attr + '="' + escapeAttribute(attrs[attr]) + '"';
14409
+ buffer += ' ' + attr + '="' + this._escapeAttribute(attrs[attr]) + '"';
13801
14410
  }
13802
14411
  }
13803
14412
 
@@ -13812,7 +14421,7 @@ Ember._RenderBuffer.prototype =
13812
14421
  if (value === true) {
13813
14422
  buffer += ' ' + prop + '="' + prop + '"';
13814
14423
  } else {
13815
- buffer += ' ' + prop + '="' + escapeAttribute(props[prop]) + '"';
14424
+ buffer += ' ' + prop + '="' + this._escapeAttribute(props[prop]) + '"';
13816
14425
  }
13817
14426
  }
13818
14427
  }
@@ -13827,7 +14436,7 @@ Ember._RenderBuffer.prototype =
13827
14436
 
13828
14437
  pushClosingTag: function() {
13829
14438
  var tagName = this.tagNames.pop();
13830
- if (tagName) { this.buffer += '</' + stripTagName(tagName) + '>'; }
14439
+ if (tagName) { this.buffer += '</' + tagName + '>'; }
13831
14440
  },
13832
14441
 
13833
14442
  currentTagName: function() {
@@ -13925,7 +14534,32 @@ Ember._RenderBuffer.prototype =
13925
14534
 
13926
14535
  innerString: function() {
13927
14536
  return this.buffer;
14537
+ },
14538
+
14539
+ _escapeAttribute: function(value) {
14540
+ // Stolen shamelessly from Handlebars
14541
+
14542
+ var escape = {
14543
+ "<": "&lt;",
14544
+ ">": "&gt;",
14545
+ '"': "&quot;",
14546
+ "'": "&#x27;",
14547
+ "`": "&#x60;"
14548
+ };
14549
+
14550
+ var badChars = /&(?!\w+;)|[<>"'`]/g;
14551
+ var possible = /[&<>"'`]/;
14552
+
14553
+ var escapeChar = function(chr) {
14554
+ return escape[chr] || "&amp;";
14555
+ };
14556
+
14557
+ var string = value.toString();
14558
+
14559
+ if(!possible.test(string)) { return string; }
14560
+ return string.replace(badChars, escapeChar);
13928
14561
  }
14562
+
13929
14563
  };
13930
14564
 
13931
14565
  })();
@@ -13951,8 +14585,7 @@ var get = Ember.get, set = Ember.set, fmt = Ember.String.fmt;
13951
14585
  @private
13952
14586
  @extends Ember.Object
13953
14587
  */
13954
- Ember.EventDispatcher = Ember.Object.extend(
13955
- /** @scope Ember.EventDispatcher.prototype */{
14588
+ Ember.EventDispatcher = Ember.Object.extend(/** @scope Ember.EventDispatcher.prototype */{
13956
14589
 
13957
14590
  /**
13958
14591
  @private
@@ -13984,7 +14617,7 @@ Ember.EventDispatcher = Ember.Object.extend(
13984
14617
  @method setup
13985
14618
  @param addedEvents {Hash}
13986
14619
  */
13987
- setup: function(addedEvents) {
14620
+ setup: function(addedEvents, rootElement) {
13988
14621
  var event, events = {
13989
14622
  touchstart : 'touchStart',
13990
14623
  touchmove : 'touchMove',
@@ -14017,7 +14650,12 @@ Ember.EventDispatcher = Ember.Object.extend(
14017
14650
 
14018
14651
  Ember.$.extend(events, addedEvents || {});
14019
14652
 
14020
- var rootElement = Ember.$(get(this, 'rootElement'));
14653
+
14654
+ if (!Ember.isNone(rootElement)) {
14655
+ set(this, 'rootElement', rootElement);
14656
+ }
14657
+
14658
+ rootElement = Ember.$(get(this, 'rootElement'));
14021
14659
 
14022
14660
  Ember.assert(fmt('You cannot use the same root element (%@) multiple times in an Ember.Application', [rootElement.selector || rootElement[0].tagName]), !rootElement.is('.ember-application'));
14023
14661
  Ember.assert('You cannot make a new Ember.Application using a root element that is a descendent of an existing Ember.Application', !rootElement.closest('.ember-application').length);
@@ -14059,7 +14697,7 @@ Ember.EventDispatcher = Ember.Object.extend(
14059
14697
  setupHandler: function(rootElement, event, eventName) {
14060
14698
  var self = this;
14061
14699
 
14062
- rootElement.delegate('.ember-view', event + '.ember', function(evt, triggeringManager) {
14700
+ rootElement.on(event + '.ember', '.ember-view', function(evt, triggeringManager) {
14063
14701
  return Ember.handleErrors(function() {
14064
14702
  var view = Ember.View.views[this.id],
14065
14703
  result = true, manager = null;
@@ -14078,7 +14716,7 @@ Ember.EventDispatcher = Ember.Object.extend(
14078
14716
  }, this);
14079
14717
  });
14080
14718
 
14081
- rootElement.delegate('[data-ember-action]', event + '.ember', function(evt) {
14719
+ rootElement.on(event + '.ember', '[data-ember-action]', function(evt) {
14082
14720
  return Ember.handleErrors(function() {
14083
14721
  var actionId = Ember.$(evt.currentTarget).attr('data-ember-action'),
14084
14722
  action = Ember.Handlebars.ActionHelper.registeredActions[actionId];
@@ -14130,7 +14768,7 @@ Ember.EventDispatcher = Ember.Object.extend(
14130
14768
 
14131
14769
  destroy: function() {
14132
14770
  var rootElement = get(this, 'rootElement');
14133
- Ember.$(rootElement).undelegate('.ember').removeClass('ember-application');
14771
+ Ember.$(rootElement).off('.ember', '**').removeClass('ember-application');
14134
14772
  return this._super();
14135
14773
  }
14136
14774
  });
@@ -14933,7 +15571,7 @@ class:
14933
15571
  eventManager: Ember.Object.create({
14934
15572
  mouseEnter: function(event, view){
14935
15573
  // view might be instance of either
14936
- // OutsideView or InnerView depending on
15574
+ // OuterView or InnerView depending on
14937
15575
  // where on the page the user interaction occured
14938
15576
  }
14939
15577
  })
@@ -15127,6 +15765,8 @@ Ember.View = Ember.CoreView.extend(
15127
15765
  templateForName: function(name, type) {
15128
15766
  if (!name) { return; }
15129
15767
  Ember.assert("templateNames are not allowed to contain periods: "+name, name.indexOf('.') === -1);
15768
+
15769
+ // the defaultContainer is deprecated
15130
15770
  var container = this.container || (Ember.Container && Ember.Container.defaultContainer);
15131
15771
  return container && container.lookup('template:' + name);
15132
15772
  },
@@ -16597,7 +17237,7 @@ Ember.View.reopenClass({
16597
17237
 
16598
17238
  // If the value is not false, undefined, or null, return the current
16599
17239
  // value of the property.
16600
- } else if (val !== false && val !== undefined && val !== null) {
17240
+ } else if (val !== false && val != null) {
16601
17241
  return val;
16602
17242
 
16603
17243
  // Nothing to display. Return null so that the old class is removed
@@ -17245,6 +17885,8 @@ Ember.ContainerView = Ember.View.extend(Ember.MutableArray, {
17245
17885
 
17246
17886
  replace: function(idx, removedCount, addedViews) {
17247
17887
  var addedCount = addedViews ? get(addedViews, 'length') : 0;
17888
+ var self = this;
17889
+ Ember.assert("You can't add a child to a container that is already a child of another view", Ember.A(addedViews).every(function(item) { return !get(item, '_parentView') || get(item, '_parentView') === self; }));
17248
17890
 
17249
17891
  this.arrayContentWillChange(idx, removedCount, addedCount);
17250
17892
  this.childViewsWillChange(this._childViews, idx, removedCount);
@@ -17285,7 +17927,7 @@ Ember.ContainerView = Ember.View.extend(Ember.MutableArray, {
17285
17927
  });
17286
17928
  },
17287
17929
 
17288
- instrumentName: 'render.container',
17930
+ instrumentName: 'container',
17289
17931
 
17290
17932
  /**
17291
17933
  @private
@@ -17365,6 +18007,7 @@ Ember.ContainerView = Ember.View.extend(Ember.MutableArray, {
17365
18007
  _currentViewDidChange: Ember.observer(function() {
17366
18008
  var currentView = get(this, 'currentView');
17367
18009
  if (currentView) {
18010
+ Ember.assert("You tried to set a current view that already has a parent. Make sure you don't have multiple outlets in the same view.", !get(currentView, '_parentView'));
17368
18011
  this.pushObject(currentView);
17369
18012
  }
17370
18013
  }, 'currentView'),
@@ -17454,7 +18097,7 @@ var get = Ember.get, set = Ember.set, fmt = Ember.String.fmt;
17454
18097
 
17455
18098
  /**
17456
18099
  `Ember.CollectionView` is an `Ember.View` descendent responsible for managing
17457
- a collection (an array or array-like object) by maintaing a child view object
18100
+ a collection (an array or array-like object) by maintaining a child view object
17458
18101
  and associated DOM representation for each item in the array and ensuring
17459
18102
  that child views and their associated rendered HTML are updated when items in
17460
18103
  the array are added, removed, or replaced.
@@ -17605,8 +18248,7 @@ var get = Ember.get, set = Ember.set, fmt = Ember.String.fmt;
17605
18248
  @extends Ember.ContainerView
17606
18249
  @since Ember 0.9
17607
18250
  */
17608
- Ember.CollectionView = Ember.ContainerView.extend(
17609
- /** @scope Ember.CollectionView.prototype */ {
18251
+ Ember.CollectionView = Ember.ContainerView.extend(/** @scope Ember.CollectionView.prototype */ {
17610
18252
 
17611
18253
  /**
17612
18254
  A list of items to be displayed by the `Ember.CollectionView`.
@@ -17732,9 +18374,10 @@ Ember.CollectionView = Ember.ContainerView.extend(
17732
18374
  This array observer is added in `contentDidChange`.
17733
18375
 
17734
18376
  @method arrayDidChange
17735
- @param {Array} addedObjects the objects that were added to the content
17736
- @param {Array} removedObjects the objects that were removed from the content
17737
- @param {Number} changeIndex the index at which the changes occurred
18377
+ @param {Array} content the managed collection of objects
18378
+ @param {Number} start the index at which the changes occurred
18379
+ @param {Number} removed number of object removed from content
18380
+ @param {Number} added number of object added to content
17738
18381
  */
17739
18382
  arrayDidChange: function(content, start, removed, added) {
17740
18383
  var itemViewClass = get(this, 'itemViewClass'),
@@ -19635,7 +20278,8 @@ if(!Handlebars && typeof require === 'function') {
19635
20278
  Handlebars = require('handlebars');
19636
20279
  }
19637
20280
 
19638
- Ember.assert("Ember Handlebars requires Handlebars 1.0.0-rc.3 or greater. Include a SCRIPT tag in the HTML HEAD linking to the Handlebars file before you link to Ember.", Handlebars && Handlebars.COMPILER_REVISION === 2);
20281
+ Ember.assert("Ember Handlebars requires Handlebars version 1.0.0-rc.4. Include a SCRIPT tag in the HTML HEAD linking to the Handlebars file before you link to Ember.", Handlebars)
20282
+ Ember.assert("Ember Handlebars requires Handlebars version 1.0.0-rc.4, COMPILER_REVISION expected: 3, got: " + Handlebars.COMPILER_REVISION + " – Please note: Builds of master may have other COMPILER_REVISION values.", Handlebars.COMPILER_REVISION === 3);
19639
20283
 
19640
20284
  /**
19641
20285
  Prepares the Handlebars templating library for use inside Ember's view
@@ -19653,10 +20297,25 @@ Ember.assert("Ember Handlebars requires Handlebars 1.0.0-rc.3 or greater. Includ
19653
20297
  */
19654
20298
  Ember.Handlebars = objectCreate(Handlebars);
19655
20299
 
20300
+ function makeBindings(options) {
20301
+ var hash = options.hash,
20302
+ hashType = options.hashTypes;
20303
+
20304
+ for (var prop in hash) {
20305
+ if (hashType[prop] === 'ID') {
20306
+ hash[prop + 'Binding'] = hash[prop];
20307
+ hashType[prop + 'Binding'] = 'STRING';
20308
+ delete hash[prop];
20309
+ delete hashType[prop];
20310
+ }
20311
+ }
20312
+ }
20313
+
19656
20314
  Ember.Handlebars.helper = function(name, value) {
19657
20315
  if (Ember.View.detect(value)) {
19658
- Ember.Handlebars.registerHelper(name, function(name, options) {
20316
+ Ember.Handlebars.registerHelper(name, function(options) {
19659
20317
  Ember.assert("You can only pass attributes as parameters to a application-defined helper", arguments.length < 3);
20318
+ makeBindings(options);
19660
20319
  return Ember.Handlebars.helpers.view.call(this, value, options);
19661
20320
  });
19662
20321
  } else {
@@ -20032,15 +20691,15 @@ Ember.Handlebars.registerHelper('helperMissing', function(path, options) {
20032
20691
  });
20033
20692
  ```
20034
20693
 
20035
- Which allows for template syntax such as {{concatenate prop1 prop2}} or
20036
- {{concatenate prop1 prop2 prop3}}. If any of the properties change,
20694
+ Which allows for template syntax such as `{{concatenate prop1 prop2}}` or
20695
+ `{{concatenate prop1 prop2 prop3}}`. If any of the properties change,
20037
20696
  the helpr will re-render. Note that dependency keys cannot be
20038
20697
  using in conjunction with multi-property helpers, since it is ambiguous
20039
20698
  which property the dependent keys would belong to.
20040
20699
 
20041
20700
  ## Use with unbound helper
20042
20701
 
20043
- The {{unbound}} helper can be used with bound helper invocations
20702
+ The `{{unbound}}` helper can be used with bound helper invocations
20044
20703
  to render them in their unbound form, e.g.
20045
20704
 
20046
20705
  ```handlebars
@@ -20050,6 +20709,10 @@ Ember.Handlebars.registerHelper('helperMissing', function(path, options) {
20050
20709
  In this example, if the name property changes, the helper
20051
20710
  will not re-render.
20052
20711
 
20712
+ ## Use with blocks not supported
20713
+
20714
+ Bound helpers do not support use with Handlebars blocks or
20715
+ the addition of child views of any kind.
20053
20716
 
20054
20717
  @method registerBoundHelper
20055
20718
  @for Ember.Handlebars
@@ -20073,6 +20736,8 @@ Ember.Handlebars.registerBoundHelper = function(name, fn) {
20073
20736
  pathRoot, path,
20074
20737
  loc, hashOption;
20075
20738
 
20739
+ Ember.assert("registerBoundHelper-generated helpers do not support use with Handlebars blocks.", !options.fn);
20740
+
20076
20741
  // Detect bound options (e.g. countBinding="otherCount")
20077
20742
  hash.boundOptions = {};
20078
20743
  for (hashOption in hash) {
@@ -20233,7 +20898,6 @@ Ember.Handlebars.template = function(spec){
20233
20898
  return t;
20234
20899
  };
20235
20900
 
20236
-
20237
20901
  })();
20238
20902
 
20239
20903
 
@@ -20253,7 +20917,7 @@ var htmlSafe = Ember.String.htmlSafe;
20253
20917
  if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.String) {
20254
20918
 
20255
20919
  /**
20256
- See {{#crossLink "Ember.String/htmlSafe"}}{{/crossLink}}
20920
+ See `Ember.String.htmlSafe`.
20257
20921
 
20258
20922
  @method htmlSafe
20259
20923
  @for String
@@ -20369,7 +21033,7 @@ Ember._Metamorph = Ember.Mixin.create({
20369
21033
  isVirtual: true,
20370
21034
  tagName: '',
20371
21035
 
20372
- instrumentName: 'render.metamorph',
21036
+ instrumentName: 'metamorph',
20373
21037
 
20374
21038
  init: function() {
20375
21039
  this._super();
@@ -20558,7 +21222,7 @@ merge(states.inDOM, {
20558
21222
  @private
20559
21223
  */
20560
21224
  Ember._HandlebarsBoundView = Ember._MetamorphView.extend({
20561
- instrumentName: 'render.boundHandlebars',
21225
+ instrumentName: 'boundHandlebars',
20562
21226
  states: states,
20563
21227
 
20564
21228
  /**
@@ -21195,7 +21859,7 @@ EmberHandlebars.registerHelper('bindAttr', function(options) {
21195
21859
 
21196
21860
  // Handle classes differently, as we can bind multiple classes
21197
21861
  var classBindings = attrs['class'];
21198
- if (classBindings !== null && classBindings !== undefined) {
21862
+ if (classBindings != null) {
21199
21863
  var classResults = EmberHandlebars.bindClasses(this, classBindings, view, dataId, options);
21200
21864
 
21201
21865
  ret.push('class="' + Handlebars.Utils.escapeExpression(classResults.join(' ')) + '"');
@@ -22047,6 +22711,7 @@ Ember.Handlebars.EachView = Ember.CollectionView.extend(Ember._Metamorph, {
22047
22711
  set(controller, 'container', get(this, 'controller.container'));
22048
22712
  set(controller, '_eachView', this);
22049
22713
  set(controller, 'target', get(this, 'controller'));
22714
+ set(controller, 'parentController', get(this, 'controller'));
22050
22715
 
22051
22716
  this.disableContentObservers(function() {
22052
22717
  set(this, 'content', controller);
@@ -22320,6 +22985,9 @@ GroupedEach.prototype = {
22320
22985
  {{/each}}
22321
22986
  ```
22322
22987
 
22988
+ Each itemController will receive a reference to the current controller as
22989
+ a `parentController` property.
22990
+
22323
22991
  @method each
22324
22992
  @for Ember.Handlebars.helpers
22325
22993
  @param [name] {String} name for item (used with `in`)
@@ -22341,6 +23009,11 @@ Ember.Handlebars.registerHelper('each', function(path, options) {
22341
23009
  options.hash.keyword = keywordName;
22342
23010
  }
22343
23011
 
23012
+ if (arguments.length === 1) {
23013
+ options = path;
23014
+ path = 'this';
23015
+ }
23016
+
22344
23017
  options.hash.dataSourceBinding = path;
22345
23018
  // Set up emptyView as a metamorph with no tag
22346
23019
  //options.hash.emptyViewClass = Ember._MetamorphView;
@@ -22459,7 +23132,7 @@ Ember.Handlebars.registerHelper('partial', function(name, options) {
22459
23132
  var view = options.data.view,
22460
23133
  underscoredName = nameParts.join("/"),
22461
23134
  template = view.templateForName(underscoredName),
22462
- deprecatedTemplate = view.templateForName(name);
23135
+ deprecatedTemplate = !template && view.templateForName(name);
22463
23136
 
22464
23137
  Ember.deprecate("You tried to render the partial " + name + ", which should be at '" + underscoredName + "', but Ember found '" + name + "'. Please use a leading underscore in your partials", template);
22465
23138
  Ember.assert("Unable to find partial with name '"+name+"'.", template || deprecatedTemplate);
@@ -22585,7 +23258,7 @@ var set = Ember.set, get = Ember.get;
22585
23258
  You can add a `label` tag yourself in the template where the `Ember.Checkbox`
22586
23259
  is being used.
22587
23260
 
22588
- ```html
23261
+ ```handlebars
22589
23262
  <label>
22590
23263
  {{view Ember.Checkbox classNames="applicaton-specific-checkbox"}}
22591
23264
  Some Title
@@ -22805,7 +23478,7 @@ Ember.TextField = Ember.View.extend(Ember.TextSupport,
22805
23478
  * `enter`: the user pressed enter
22806
23479
  * `keypress`: the user pressed a key
22807
23480
 
22808
- @property on
23481
+ @property onEvent
22809
23482
  @type String
22810
23483
  @default enter
22811
23484
  */
@@ -23372,34 +24045,38 @@ Ember.Select = Ember.View.extend(
23372
24045
  tagName: 'select',
23373
24046
  classNames: ['ember-select'],
23374
24047
  defaultTemplate: Ember.Handlebars.template(function anonymous(Handlebars,depth0,helpers,partials,data) {
23375
- this.compilerInfo = [2,'>= 1.0.0-rc.3'];
24048
+ this.compilerInfo = [3,'>= 1.0.0-rc.4'];
23376
24049
  helpers = helpers || Ember.Handlebars.helpers; data = data || {};
23377
- var buffer = '', stack1, hashTypes, escapeExpression=this.escapeExpression, self=this;
24050
+ var buffer = '', stack1, hashTypes, hashContexts, escapeExpression=this.escapeExpression, self=this;
23378
24051
 
23379
24052
  function program1(depth0,data) {
23380
24053
 
23381
- var buffer = '', hashTypes;
24054
+ var buffer = '', hashTypes, hashContexts;
23382
24055
  data.buffer.push("<option value=\"\">");
23383
24056
  hashTypes = {};
23384
- data.buffer.push(escapeExpression(helpers._triageMustache.call(depth0, "view.prompt", {hash:{},contexts:[depth0],types:["ID"],hashTypes:hashTypes,data:data})));
24057
+ hashContexts = {};
24058
+ data.buffer.push(escapeExpression(helpers._triageMustache.call(depth0, "view.prompt", {hash:{},contexts:[depth0],types:["ID"],hashContexts:hashContexts,hashTypes:hashTypes,data:data})));
23385
24059
  data.buffer.push("</option>");
23386
24060
  return buffer;
23387
24061
  }
23388
24062
 
23389
24063
  function program3(depth0,data) {
23390
24064
 
23391
- var hashTypes;
24065
+ var hashContexts, hashTypes;
24066
+ hashContexts = {'contentBinding': depth0};
23392
24067
  hashTypes = {'contentBinding': "STRING"};
23393
24068
  data.buffer.push(escapeExpression(helpers.view.call(depth0, "view.optionView", {hash:{
23394
24069
  'contentBinding': ("this")
23395
- },contexts:[depth0],types:["ID"],hashTypes:hashTypes,data:data})));
24070
+ },contexts:[depth0],types:["ID"],hashContexts:hashContexts,hashTypes:hashTypes,data:data})));
23396
24071
  }
23397
24072
 
23398
24073
  hashTypes = {};
23399
- stack1 = helpers['if'].call(depth0, "view.prompt", {hash:{},inverse:self.noop,fn:self.program(1, program1, data),contexts:[depth0],types:["ID"],hashTypes:hashTypes,data:data});
24074
+ hashContexts = {};
24075
+ stack1 = helpers['if'].call(depth0, "view.prompt", {hash:{},inverse:self.noop,fn:self.program(1, program1, data),contexts:[depth0],types:["ID"],hashContexts:hashContexts,hashTypes:hashTypes,data:data});
23400
24076
  if(stack1 || stack1 === 0) { data.buffer.push(stack1); }
23401
24077
  hashTypes = {};
23402
- stack1 = helpers.each.call(depth0, "view.content", {hash:{},inverse:self.noop,fn:self.program(3, program3, data),contexts:[depth0],types:["ID"],hashTypes:hashTypes,data:data});
24078
+ hashContexts = {};
24079
+ stack1 = helpers.each.call(depth0, "view.content", {hash:{},inverse:self.noop,fn:self.program(3, program3, data),contexts:[depth0],types:["ID"],hashContexts:hashContexts,hashTypes:hashTypes,data:data});
23403
24080
  if(stack1 || stack1 === 0) { data.buffer.push(stack1); }
23404
24081
  return buffer;
23405
24082
 
@@ -23537,9 +24214,9 @@ function program3(depth0,data) {
23537
24214
  selection;
23538
24215
 
23539
24216
  if (value !== selectedValue) {
23540
- selection = content.find(function(obj) {
24217
+ selection = content ? content.find(function(obj) {
23541
24218
  return value === (valuePath ? get(obj, valuePath) : obj);
23542
- });
24219
+ }) : null;
23543
24220
 
23544
24221
  this.set('selection', selection);
23545
24222
  }
@@ -23561,7 +24238,7 @@ function program3(depth0,data) {
23561
24238
  content = get(this, 'content'),
23562
24239
  prompt = get(this, 'prompt');
23563
24240
 
23564
- if (!get(content, 'length')) { return; }
24241
+ if (!content || !get(content, 'length')) { return; }
23565
24242
  if (prompt && selectedIndex === 0) { set(this, 'selection', null); return; }
23566
24243
 
23567
24244
  if (prompt) { selectedIndex -= 1; }
@@ -23642,6 +24319,15 @@ function normalizeHash(hash, hashTypes) {
23642
24319
  }
23643
24320
  }
23644
24321
 
24322
+ /**
24323
+ * `{{input}}` inserts a new instance of either Ember.TextField or
24324
+ * Ember.Checkbox, depending on the `type` option passed in. If no `type`
24325
+ * is supplied it defaults to Ember.TextField.
24326
+ *
24327
+ * @method input
24328
+ * @for Ember.Handlebars.helpers
24329
+ * @param {Hash} options
24330
+ */
23645
24331
  Ember.Handlebars.registerHelper('input', function(options) {
23646
24332
  Ember.assert('You can only pass attributes to the `input` helper, not arguments', arguments.length < 2);
23647
24333
 
@@ -23664,6 +24350,14 @@ Ember.Handlebars.registerHelper('input', function(options) {
23664
24350
  }
23665
24351
  });
23666
24352
 
24353
+ /**
24354
+ * `{{textarea}}` inserts a new instance of Ember.TextArea into the template
24355
+ * passing its options to `Ember.TextArea`'s `create` method.
24356
+ *
24357
+ * @method textarea
24358
+ * @for Ember.Handlebars.helpers
24359
+ * @param {Hash} options
24360
+ */
23667
24361
  Ember.Handlebars.registerHelper('textarea', function(options) {
23668
24362
  Ember.assert('You can only pass attributes to the `textarea` helper, not arguments', arguments.length < 2);
23669
24363
 
@@ -24121,8 +24815,7 @@ var get = Ember.get, set = Ember.set;
24121
24815
  @namespace Ember
24122
24816
  @extends Ember.Namespace
24123
24817
  */
24124
- Ember.Application = Ember.Namespace.extend(
24125
- /** @scope Ember.Application.prototype */{
24818
+ Ember.Application = Ember.Namespace.extend(/** @scope Ember.Application.prototype */{
24126
24819
 
24127
24820
  /**
24128
24821
  The root DOM element of the Application. This can be specified as an
@@ -24471,7 +25164,6 @@ Ember.Application.registerInjection({
24471
25164
 
24472
25165
  Ember.runLoadHooks('Ember.Application', Ember.Application);
24473
25166
 
24474
-
24475
25167
  })();
24476
25168
 
24477
25169
 
@@ -25351,7 +26043,7 @@ Ember.HashLocation = Ember.Object.extend({
25351
26043
  var self = this;
25352
26044
  var guid = Ember.guidFor(this);
25353
26045
 
25354
- Ember.$(window).bind('hashchange.ember-location-'+guid, function() {
26046
+ Ember.$(window).on('hashchange.ember-location-'+guid, function() {
25355
26047
  var path = location.hash.substr(1);
25356
26048
  if (get(self, 'lastSetURL') === path) { return; }
25357
26049
 
@@ -25509,7 +26201,7 @@ Ember.HistoryLocation = Ember.Object.extend({
25509
26201
  onUpdateURL: function(callback) {
25510
26202
  var guid = Ember.guidFor(this);
25511
26203
 
25512
- Ember.$(window).bind('popstate.ember-location-'+guid, function(e) {
26204
+ Ember.$(window).on('popstate.ember-location-'+guid, function(e) {
25513
26205
  if(!popstateReady) {
25514
26206
  return;
25515
26207
  }
@@ -26037,8 +26729,7 @@ var get = Ember.get, set = Ember.set;
26037
26729
  @namespace Ember
26038
26730
  @extends Ember.StateManager
26039
26731
  */
26040
- Ember.Router = Ember.StateManager.extend(
26041
- /** @scope Ember.Router.prototype */ {
26732
+ Ember.Router = Ember.StateManager.extend(/** @scope Ember.Router.prototype */ {
26042
26733
 
26043
26734
  /**
26044
26735
  @property initialState