ember-source 1.3.2 → 1.4.0.beta.1

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

Potentially problematic release.


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

data/dist/ember-debug.js CHANGED
@@ -7,7 +7,7 @@ var Ember = { assert: function() {}, FEATURES: { isEnabled: function() {} } };
7
7
  * Portions Copyright 2008-2011 Apple Inc. All rights reserved.
8
8
  * @license Licensed under MIT license
9
9
  * See https://raw.github.com/emberjs/ember.js/master/LICENSE
10
- * @version 1.3.2
10
+ * @version 1.4.0-beta.1
11
11
  */
12
12
 
13
13
 
@@ -72,11 +72,6 @@ if (!('MANDATORY_SETTER' in Ember.ENV)) {
72
72
  */
73
73
  Ember.assert = function(desc, test) {
74
74
  if (!test) {
75
- Ember.Logger.assert(test, desc);
76
- }
77
-
78
- if (Ember.testing && !test) {
79
- // when testing, ensure test failures when assertions fail
80
75
  throw new Ember.Error("Assertion Failed: " + desc);
81
76
  }
82
77
  };
@@ -5,7 +5,7 @@
5
5
  * Portions Copyright 2008-2011 Apple Inc. All rights reserved.
6
6
  * @license Licensed under MIT license
7
7
  * See https://raw.github.com/emberjs/ember.js/master/LICENSE
8
- * @version 1.3.2
8
+ * @version 1.4.0-beta.1+canary.64fee6ed
9
9
  */
10
10
 
11
11
 
@@ -70,11 +70,6 @@ if (!('MANDATORY_SETTER' in Ember.ENV)) {
70
70
  */
71
71
  Ember.assert = function(desc, test) {
72
72
  if (!test) {
73
- Ember.Logger.assert(test, desc);
74
- }
75
-
76
- if (Ember.testing && !test) {
77
- // when testing, ensure test failures when assertions fail
78
73
  throw new Ember.Error("Assertion Failed: " + desc);
79
74
  }
80
75
  };
@@ -203,7 +198,7 @@ if (!Ember.testing) {
203
198
  * Portions Copyright 2008-2011 Apple Inc. All rights reserved.
204
199
  * @license Licensed under MIT license
205
200
  * See https://raw.github.com/emberjs/ember.js/master/LICENSE
206
- * @version 1.3.2
201
+ * @version 1.4.0-beta.1+canary.64fee6ed
207
202
  */
208
203
 
209
204
 
@@ -286,7 +281,7 @@ var define, requireModule, require, requirejs;
286
281
 
287
282
  @class Ember
288
283
  @static
289
- @version 1.3.2
284
+ @version 1.4.0-beta.1+canary.64fee6ed
290
285
  */
291
286
 
292
287
  if ('undefined' === typeof Ember) {
@@ -313,10 +308,10 @@ Ember.toString = function() { return "Ember"; };
313
308
  /**
314
309
  @property VERSION
315
310
  @type String
316
- @default '1.3.2'
311
+ @default '1.4.0-beta.1+canary.64fee6ed'
317
312
  @static
318
313
  */
319
- Ember.VERSION = '1.3.2';
314
+ Ember.VERSION = '1.4.0-beta.1+canary.64fee6ed';
320
315
 
321
316
  /**
322
317
  Standard environmental variables. You can define these in a global `EmberENV`
@@ -791,17 +786,19 @@ var arrayIndexOf = isNativeFunc(Array.prototype.indexOf) ? Array.prototype.index
791
786
  return -1;
792
787
  };
793
788
 
794
- /**
795
- Array polyfills to support ES5 features in older browsers.
796
789
 
797
- @namespace Ember
798
- @property ArrayPolyfills
799
- */
800
- Ember.ArrayPolyfills = {
801
- map: arrayMap,
802
- forEach: arrayForEach,
803
- indexOf: arrayIndexOf
804
- };
790
+ /**
791
+ Array polyfills to support ES5 features in older browsers.
792
+
793
+ @namespace Ember
794
+ @property ArrayPolyfills
795
+ */
796
+ Ember.ArrayPolyfills = {
797
+ map: arrayMap,
798
+ forEach: arrayForEach,
799
+ indexOf: arrayIndexOf
800
+ };
801
+
805
802
 
806
803
  if (Ember.SHIM_ES5) {
807
804
  if (!Array.prototype.map) {
@@ -1069,7 +1066,8 @@ Meta.prototype = {
1069
1066
  bindings: null,
1070
1067
  chains: null,
1071
1068
  chainWatchers: null,
1072
- values: null
1069
+ values: null,
1070
+ proto: null
1073
1071
  };
1074
1072
 
1075
1073
  if (isDefinePropertySimulated) {
@@ -1576,6 +1574,41 @@ Ember.typeOf = function(item) {
1576
1574
  return ret;
1577
1575
  };
1578
1576
 
1577
+ /**
1578
+ Convenience method to inspect an object. This method will attempt to
1579
+ convert the object into a useful string description.
1580
+
1581
+ It is a pretty simple implementation. If you want something more robust,
1582
+ use something like JSDump: https://github.com/NV/jsDump
1583
+
1584
+ @method inspect
1585
+ @for Ember
1586
+ @param {Object} obj The object you want to inspect.
1587
+ @return {String} A description of the object
1588
+ */
1589
+ Ember.inspect = function(obj) {
1590
+ var type = Ember.typeOf(obj);
1591
+ if (type === 'array') {
1592
+ return '[' + obj + ']';
1593
+ }
1594
+ if (type !== 'object') {
1595
+ return obj + '';
1596
+ }
1597
+
1598
+ var v, ret = [];
1599
+ for(var key in obj) {
1600
+ if (obj.hasOwnProperty(key)) {
1601
+ v = obj[key];
1602
+ if (v === 'toString') { continue; } // ignore useless items
1603
+ if (Ember.typeOf(v) === 'function') { v = "function() { ... }"; }
1604
+ ret.push(key + ": " + v);
1605
+ }
1606
+ }
1607
+ return "{" + ret.join(", ") + "}";
1608
+ };
1609
+
1610
+
1611
+
1579
1612
  })();
1580
1613
 
1581
1614
 
@@ -1790,10 +1823,11 @@ Ember.subscribe = Ember.Instrumentation.subscribe;
1790
1823
 
1791
1824
 
1792
1825
  (function() {
1793
- var map, forEach, indexOf, splice;
1826
+ var map, forEach, indexOf, splice, filter;
1794
1827
  map = Array.prototype.map || Ember.ArrayPolyfills.map;
1795
1828
  forEach = Array.prototype.forEach || Ember.ArrayPolyfills.forEach;
1796
1829
  indexOf = Array.prototype.indexOf || Ember.ArrayPolyfills.indexOf;
1830
+ filter = Array.prototype.filter || Ember.ArrayPolyfills.filter;
1797
1831
  splice = Array.prototype.splice;
1798
1832
 
1799
1833
  var utils = Ember.EnumerableUtils = {
@@ -1805,6 +1839,10 @@ var utils = Ember.EnumerableUtils = {
1805
1839
  return obj.forEach ? obj.forEach.call(obj, callback, thisArg) : forEach.call(obj, callback, thisArg);
1806
1840
  },
1807
1841
 
1842
+ filter: function(obj, callback, thisArg) {
1843
+ return obj.filter ? obj.filter.call(obj, callback, thisArg) : filter.call(obj, callback, thisArg);
1844
+ },
1845
+
1808
1846
  indexOf: function(obj, element, index) {
1809
1847
  return obj.indexOf ? obj.indexOf.call(obj, element, index) : indexOf.call(obj, element, index);
1810
1848
  },
@@ -1986,7 +2024,7 @@ var normalizeTuple = Ember.normalizeTuple = function(target, path) {
1986
2024
  }
1987
2025
 
1988
2026
  // must return some kind of path to be valid else other things will break.
1989
- if (!path || path.length===0) throw new Ember.Error('Invalid Path');
2027
+ if (!path || path.length===0) throw new Ember.Error('Path cannot be empty');
1990
2028
 
1991
2029
  return [ target, path ];
1992
2030
  };
@@ -3523,6 +3561,12 @@ Ember.defineProperty = function(obj, keyName, desc, data, meta) {
3523
3561
  } else {
3524
3562
  obj[keyName] = undefined; // make enumerable
3525
3563
  }
3564
+
3565
+
3566
+ if (desc.func && desc._dependentCPs) {
3567
+ addImplicitCPs(obj, desc._dependentCPs, meta);
3568
+ }
3569
+
3526
3570
  } else {
3527
3571
  descs[keyName] = undefined; // shadow descriptor in proto
3528
3572
  if (desc == null) {
@@ -3559,6 +3603,22 @@ Ember.defineProperty = function(obj, keyName, desc, data, meta) {
3559
3603
  };
3560
3604
 
3561
3605
 
3606
+ var addImplicitCPs = function defineImplicitCPs(obj, implicitCPs, meta) {
3607
+ var cp, key, length = implicitCPs.length;
3608
+
3609
+ for (var i=0; i<length; ++i) {
3610
+ cp = implicitCPs[i];
3611
+ key = cp.implicitCPKey;
3612
+
3613
+ Ember.defineProperty(obj, key, cp, undefined, meta);
3614
+
3615
+ if (cp._dependentCPs) {
3616
+ addImplicitCPs(obj, cp._dependentCPs, meta);
3617
+ }
3618
+ }
3619
+ };
3620
+
3621
+
3562
3622
  })();
3563
3623
 
3564
3624
 
@@ -4043,6 +4103,52 @@ Ember.finishChains = function(obj) {
4043
4103
 
4044
4104
  (function() {
4045
4105
 
4106
+ /**
4107
+ @module ember-metal
4108
+ */
4109
+
4110
+ var forEach = Ember.EnumerableUtils.forEach,
4111
+ BRACE_EXPANSION = /^((?:[^\.]*\.)*)\{(.*)\}$/;
4112
+
4113
+ /**
4114
+ Expands `pattern`, invoking `callback` for each expansion.
4115
+
4116
+ The only pattern supported is brace-expansion, anything else will be passed
4117
+ once to `callback` directly. Brace expansion can only appear at the end of a
4118
+ pattern, for example as the last item in a chain.
4119
+
4120
+ Example
4121
+ ```js
4122
+ function echo(arg){ console.log(arg); }
4123
+
4124
+ Ember.expandProperties('foo.bar', echo); //=> 'foo.bar'
4125
+ Ember.expandProperties('{foo,bar}', echo); //=> 'foo', 'bar'
4126
+ Ember.expandProperties('foo.{bar,baz}', echo); //=> 'foo.bar', 'foo.baz'
4127
+ Ember.expandProperties('{foo,bar}.baz', echo); //=> '{foo,bar}.baz'
4128
+ ```
4129
+
4130
+ @method
4131
+ @private
4132
+ @param {string} pattern The property pattern to expand.
4133
+ @param {function} callback The callback to invoke. It is invoked once per
4134
+ expansion, and is passed the expansion.
4135
+ */
4136
+ Ember.expandProperties = function (pattern, callback) {
4137
+ var match, prefix, list;
4138
+
4139
+ if (match = BRACE_EXPANSION.exec(pattern)) {
4140
+ prefix = match[1];
4141
+ list = match[2];
4142
+
4143
+ forEach(list.split(','), function (suffix) {
4144
+ callback(prefix + suffix);
4145
+ });
4146
+ } else {
4147
+ callback(pattern);
4148
+ }
4149
+ };
4150
+
4151
+
4046
4152
  })();
4047
4153
 
4048
4154
 
@@ -4246,6 +4352,13 @@ var get = Ember.get,
4246
4352
  unwatch = Ember.unwatch;
4247
4353
 
4248
4354
 
4355
+
4356
+
4357
+
4358
+
4359
+ var expandProperties = Ember.expandProperties;
4360
+
4361
+
4249
4362
  // ..........................................................
4250
4363
  // DEPENDENT KEYS
4251
4364
  //
@@ -4404,9 +4517,10 @@ function removeDependentKeys(desc, obj, keyName, meta) {
4404
4517
  */
4405
4518
  function ComputedProperty(func, opts) {
4406
4519
  this.func = func;
4407
-
4520
+
4521
+ setDependentKeys(this, opts && opts.dependentKeys);
4522
+
4408
4523
  this._cacheable = (opts && opts.cacheable !== undefined) ? opts.cacheable : true;
4409
- this._dependentKeys = opts && opts.dependentKeys;
4410
4524
  this._readOnly = opts && (opts.readOnly !== undefined || !!opts.readOnly);
4411
4525
  }
4412
4526
 
@@ -4415,6 +4529,15 @@ ComputedProperty.prototype = new Ember.Descriptor();
4415
4529
 
4416
4530
  var ComputedPropertyPrototype = ComputedProperty.prototype;
4417
4531
 
4532
+
4533
+ ComputedPropertyPrototype.toString = function() {
4534
+ if (this.implicitCPKey) {
4535
+ return this.implicitCPKey;
4536
+ }
4537
+ return Ember.Descriptor.prototype.toString.apply(this, arguments);
4538
+ };
4539
+
4540
+
4418
4541
  /**
4419
4542
  Properties are cacheable by default. Computed property will automatically
4420
4543
  cache the return value of your function until one of the dependent keys changes.
@@ -4510,10 +4633,18 @@ ComputedPropertyPrototype.property = function() {
4510
4633
  var args;
4511
4634
 
4512
4635
 
4513
- args = a_slice.call(arguments);
4514
-
4636
+ var addArg = function (property) {
4637
+ args.push(property);
4638
+ };
4515
4639
 
4516
- this._dependentKeys = args;
4640
+ args = [];
4641
+ for (var i = 0, l = arguments.length; i < l; i++) {
4642
+ expandProperties(arguments[i], addArg);
4643
+ }
4644
+
4645
+
4646
+ setDependentKeys(this, args);
4647
+
4517
4648
  return this;
4518
4649
  };
4519
4650
 
@@ -4640,7 +4771,7 @@ ComputedPropertyPrototype.set = function(obj, keyName, value) {
4640
4771
  funcArgLength, cachedValue, ret;
4641
4772
 
4642
4773
  if (this._readOnly) {
4643
- throw new Ember.Error('Cannot Set: ' + keyName + ' on: ' + obj.toString() );
4774
+ throw new Ember.Error('Cannot Set: ' + keyName + ' on: ' + Ember.inspect(obj));
4644
4775
  }
4645
4776
 
4646
4777
  this._suspended = obj;
@@ -4771,26 +4902,87 @@ function getProperties(self, propertyNames) {
4771
4902
  return ret;
4772
4903
  }
4773
4904
 
4774
- function registerComputed(name, macro) {
4775
- Ember.computed[name] = function(dependentKey) {
4776
- var args = a_slice.call(arguments);
4777
- return Ember.computed(dependentKey, function() {
4778
- return macro.apply(this, args);
4779
- });
4905
+ var registerComputed, registerComputedWithProperties;
4906
+
4907
+
4908
+ var guidFor = Ember.guidFor,
4909
+ map = Ember.EnumerableUtils.map,
4910
+ filter = Ember.EnumerableUtils.filter,
4911
+ typeOf = Ember.typeOf;
4912
+
4913
+ var implicitKey = function (cp) {
4914
+ return [guidFor(cp)].concat(cp._dependentKeys).join('_');
4780
4915
  };
4781
- }
4782
4916
 
4783
- function registerComputedWithProperties(name, macro) {
4784
- Ember.computed[name] = function() {
4785
- var properties = a_slice.call(arguments);
4917
+ var normalizeDependentKey = function (key) {
4918
+ if (key instanceof Ember.ComputedProperty) {
4919
+ return implicitKey(key);
4920
+ } else if (typeof key === 'string' || key instanceof String || typeof key === 'object' || typeof key === 'number') {
4921
+ return key;
4922
+ } else {
4923
+ Ember.assert('Unexpected dependent key ' + key + ' of type ' + typeof(key), false);
4924
+ }
4925
+ };
4786
4926
 
4787
- var computed = Ember.computed(function() {
4788
- return macro.apply(this, [getProperties(this, properties)]);
4927
+ var normalizeDependentKeys = function (keys) {
4928
+ return map(keys, function (key) {
4929
+ return normalizeDependentKey(key);
4789
4930
  });
4931
+ };
4790
4932
 
4791
- return computed.property.apply(computed, properties);
4933
+ var selectDependentCPs = function (keys) {
4934
+ return filter(keys, function (key) {
4935
+ return key instanceof Ember.ComputedProperty;
4936
+ });
4792
4937
  };
4793
- }
4938
+
4939
+ var setDependentKeys = function(cp, dependentKeys) {
4940
+ if (dependentKeys) {
4941
+ cp._dependentKeys = normalizeDependentKeys(dependentKeys);
4942
+ cp._dependentCPs = selectDependentCPs(dependentKeys);
4943
+ cp.implicitCPKey = implicitKey(cp);
4944
+ } else {
4945
+ cp._dependentKeys = cp._dependentCPs = [];
4946
+ delete cp.implicitCPKey;
4947
+ }
4948
+ };
4949
+ // expose `normalizeDependentKey[s]` so user CP macros can easily support
4950
+ // composition
4951
+ Ember.computed.normalizeDependentKey = normalizeDependentKey;
4952
+ Ember.computed.normalizeDependentKeys = normalizeDependentKeys;
4953
+
4954
+ registerComputed = function (name, macro) {
4955
+ Ember.computed[name] = function(dependentKey) {
4956
+ var args = normalizeDependentKeys(a_slice.call(arguments));
4957
+ return Ember.computed(dependentKey, function() {
4958
+ return macro.apply(this, args);
4959
+ });
4960
+ };
4961
+ };
4962
+
4963
+
4964
+
4965
+ registerComputedWithProperties = function(name, macro) {
4966
+ Ember.computed[name] = function() {
4967
+ var args = a_slice.call(arguments);
4968
+ var properties = normalizeDependentKeys(args);
4969
+
4970
+ var computed = Ember.computed(function() {
4971
+ return macro.apply(this, [getProperties(this, properties)]);
4972
+ });
4973
+
4974
+ return computed.property.apply(computed, args);
4975
+ };
4976
+ };
4977
+
4978
+
4979
+
4980
+ Ember.computed.literal = function (value) {
4981
+ return Ember.computed(function () {
4982
+ return value;
4983
+ });
4984
+ };
4985
+
4794
4986
 
4795
4987
  /**
4796
4988
  A computed property that returns true if the value of the dependent
@@ -5321,7 +5513,51 @@ Ember.computed.oneWay = function(dependentKey) {
5321
5513
  });
5322
5514
  };
5323
5515
 
5516
+ if (Ember.FEATURES.isEnabled('computed-read-only')) {
5517
+ /**
5518
+ Where `computed.oneWay` provides oneWay bindings, `computed.readOnly` provides
5519
+ a readOnly one way binding. Very often when using `computed.oneWay` one does
5520
+ not also want changes to propogate back up, as they will replace the value.
5521
+
5522
+ This prevents the reverse flow, and also throws an exception when it occurs.
5523
+
5524
+ Example
5525
+
5526
+ ```javascript
5527
+ User = Ember.Object.extend({
5528
+ firstName: null,
5529
+ lastName: null,
5530
+ nickName: Ember.computed.readOnly('firstName')
5531
+ });
5324
5532
 
5533
+ user = User.create({
5534
+ firstName: 'Teddy',
5535
+ lastName: 'Zeenny'
5536
+ });
5537
+
5538
+ user.get('nickName');
5539
+ # 'Teddy'
5540
+
5541
+ user.set('nickName', 'TeddyBear');
5542
+ # throws Exception
5543
+ # throw new Ember.Error('Cannot Set: nickName on: <User:ember27288>' );`
5544
+
5545
+ user.get('firstName');
5546
+ # 'Teddy'
5547
+ ```
5548
+
5549
+ @method computed.readOnly
5550
+ @for Ember
5551
+ @param {String} dependentKey
5552
+ @return {Ember.ComputedProperty} computed property which creates a
5553
+ one way computed property to the original value for property.
5554
+ */
5555
+ Ember.computed.readOnly = function(dependentKey) {
5556
+ return Ember.computed(dependentKey, function() {
5557
+ return get(this, dependentKey);
5558
+ }).readOnly();
5559
+ };
5560
+ }
5325
5561
  /**
5326
5562
  A computed property that acts like a standard getter and setter,
5327
5563
  but returns the value at the provided `defaultPath` if the
@@ -6135,7 +6371,8 @@ var Backburner = requireModule('backburner').Backburner,
6135
6371
  onBegin: onBegin,
6136
6372
  onEnd: onEnd
6137
6373
  }),
6138
- slice = [].slice;
6374
+ slice = [].slice,
6375
+ concat = [].concat;
6139
6376
 
6140
6377
  // ..........................................................
6141
6378
  // Ember.run - this is ideally the only public API the dev sees
@@ -6221,7 +6458,7 @@ Ember.run = function(target, method) {
6221
6458
  @return {Object} Return value from invoking the passed function. Please note,
6222
6459
  when called within an existing loop, no return value is possible.
6223
6460
  */
6224
- Ember.run.join = function(target, method) {
6461
+ Ember.run.join = function(target, method /* args */) {
6225
6462
  if (!Ember.run.currentRunLoop) {
6226
6463
  return Ember.run.apply(Ember.run, arguments);
6227
6464
  }
@@ -6231,6 +6468,55 @@ Ember.run.join = function(target, method) {
6231
6468
  Ember.run.schedule.apply(Ember.run, args);
6232
6469
  };
6233
6470
 
6471
+
6472
+ /**
6473
+ Provides a useful utility for when integrating with non-Ember libraries
6474
+ that provide asynchronous callbacks.
6475
+
6476
+ Ember utilizes a run-loop to batch and coalesce changes. This works by
6477
+ marking the start and end of Ember-related Javascript execution.
6478
+
6479
+ When using events such as a View's click handler, Ember wraps the event
6480
+ handler in a run-loop, but when integrating with non-Ember libraries this
6481
+ can be tedious.
6482
+
6483
+ For example, the following is rather verbose but is the correct way to combine
6484
+ third-party events and Ember code.
6485
+
6486
+ ```javascript
6487
+ var that = this;
6488
+ jQuery(window).on('resize', function(){
6489
+ Ember.run(function(){
6490
+ that.handleResize();
6491
+ });
6492
+ });
6493
+ ```
6494
+
6495
+ To reduce the boilerplate, the following can be used to construct a
6496
+ run-loop-wrapped callback handler.
6497
+
6498
+ ```javascript
6499
+ jQuery(window).on('resize', Ember.run.bind(this, this.triggerResize));
6500
+ ```
6501
+
6502
+ @method bind
6503
+ @namespace Ember.run
6504
+ @param {Object} [target] target of method to call
6505
+ @param {Function|String} method Method to invoke.
6506
+ May be a function or a string. If you pass a string
6507
+ then it will be looked up on the passed target.
6508
+ @param {Object} [args*] Any additional arguments you wish to pass to the method.
6509
+ @return {Object} return value from invoking the passed function. Please note,
6510
+ when called within an existing loop, no return value is possible.
6511
+ */
6512
+ Ember.run.bind = function(target, method /* args*/) {
6513
+ var args = arguments;
6514
+ return function() {
6515
+ return Ember.run.join.apply(Ember.run, args);
6516
+ };
6517
+ };
6518
+
6519
+
6234
6520
  Ember.run.backburner = backburner;
6235
6521
 
6236
6522
  var run = Ember.run;
@@ -6400,7 +6686,7 @@ Ember.run.later = function(target, method) {
6400
6686
  If you pass a string it will be resolved on the
6401
6687
  target at the time the method is invoked.
6402
6688
  @param {Object} [args*] Optional arguments to pass to the timeout.
6403
- @return {Object} timer
6689
+ @return {Object} Timer information for use in cancelling, see `Ember.run.cancel`.
6404
6690
  */
6405
6691
  Ember.run.once = function(target, method) {
6406
6692
  checkAutoRun();
@@ -6451,7 +6737,7 @@ Ember.run.once = function(target, method) {
6451
6737
  If you pass a string it will be resolved on the
6452
6738
  target at the time the method is invoked.
6453
6739
  @param {Object} [args*] Optional arguments to pass to the timeout.
6454
- @return {Object} timer
6740
+ @return {Object} Timer information for use in cancelling, see `Ember.run.cancel`.
6455
6741
  */
6456
6742
  Ember.run.scheduleOnce = function(queue, target, method) {
6457
6743
  checkAutoRun();
@@ -6514,7 +6800,7 @@ Ember.run.scheduleOnce = function(queue, target, method) {
6514
6800
  If you pass a string it will be resolved on the
6515
6801
  target at the time the method is invoked.
6516
6802
  @param {Object} [args*] Optional arguments to pass to the timeout.
6517
- @return {Object} timer
6803
+ @return {Object} Timer information for use in cancelling, see `Ember.run.cancel`.
6518
6804
  */
6519
6805
  Ember.run.next = function() {
6520
6806
  var args = slice.call(arguments);
@@ -6524,7 +6810,8 @@ Ember.run.next = function() {
6524
6810
 
6525
6811
  /**
6526
6812
  Cancels a scheduled item. Must be a value returned by `Ember.run.later()`,
6527
- `Ember.run.once()`, or `Ember.run.next()`.
6813
+ `Ember.run.once()`, `Ember.run.next()`, `Ember.run.debounce()`, or
6814
+ `Ember.run.throttle()`.
6528
6815
 
6529
6816
  ```javascript
6530
6817
  var runNext = Ember.run.next(myContext, function() {
@@ -6541,11 +6828,29 @@ Ember.run.next = function() {
6541
6828
  // will not be executed
6542
6829
  });
6543
6830
  Ember.run.cancel(runOnce);
6831
+
6832
+ var throttle = Ember.run.throttle(myContext, function() {
6833
+ // will not be executed
6834
+ }, 1);
6835
+ Ember.run.cancel(throttle);
6836
+
6837
+ var debounce = Ember.run.debounce(myContext, function() {
6838
+ // will not be executed
6839
+ }, 1);
6840
+ Ember.run.cancel(debounce);
6841
+
6842
+ var debounceImmediate = Ember.run.debounce(myContext, function() {
6843
+ // will be executed since we passed in true (immediate)
6844
+ }, 100, true);
6845
+ // the 100ms delay until this method can be called again will be cancelled
6846
+ Ember.run.cancel(debounceImmediate);
6847
+ ```
6848
+ ```
6544
6849
  ```
6545
6850
 
6546
6851
  @method cancel
6547
6852
  @param {Object} timer Timer object to cancel
6548
- @return {void}
6853
+ @return {Boolean} true if cancelled or false/undefined if it wasn't found
6549
6854
  */
6550
6855
  Ember.run.cancel = function(timer) {
6551
6856
  return backburner.cancel(timer);
@@ -6577,6 +6882,34 @@ Ember.run.cancel = function(timer) {
6577
6882
  // console logs 'debounce ran.' one time.
6578
6883
  ```
6579
6884
 
6885
+ Immediate allows you to run the function immediately, but debounce
6886
+ other calls for this function until the wait time has elapsed. If
6887
+ `debounce` is called again before the specified time has elapsed,
6888
+ the timer is reset and the entire period msut pass again before
6889
+ the method can be called again.
6890
+
6891
+ ```javascript
6892
+ var myFunc = function() { console.log(this.name + ' ran.'); };
6893
+ var myContext = {name: 'debounce'};
6894
+
6895
+ Ember.run.debounce(myContext, myFunc, 150, true);
6896
+
6897
+ // console logs 'debounce ran.' one time immediately.
6898
+ // 100ms passes
6899
+
6900
+ Ember.run.debounce(myContext, myFunc, 150, true);
6901
+
6902
+ // 150ms passes and nothing else is logged to the console and
6903
+ // the debouncee is no longer being watched
6904
+
6905
+ Ember.run.debounce(myContext, myFunc, 150, true);
6906
+
6907
+ // console logs 'debounce ran.' one time immediately.
6908
+ // 150ms passes and nothing else is logged tot he console and
6909
+ // the debouncee is no longer being watched
6910
+
6911
+ ```
6912
+
6580
6913
  @method debounce
6581
6914
  @param {Object} [target] target of method to invoke
6582
6915
  @param {Function|String} method The method to invoke.
@@ -6585,7 +6918,7 @@ Ember.run.cancel = function(timer) {
6585
6918
  @param {Object} [args*] Optional arguments to pass to the timeout.
6586
6919
  @param {Number} wait Number of milliseconds to wait.
6587
6920
  @param {Boolean} immediate Trigger the function on the leading instead of the trailing edge of the wait interval.
6588
- @return {void}
6921
+ @return {Array} Timer information for use in cancelling, see `Ember.run.cancel`.
6589
6922
  */
6590
6923
  Ember.run.debounce = function() {
6591
6924
  return backburner.debounce.apply(backburner, arguments);
@@ -6622,7 +6955,7 @@ Ember.run.debounce = function() {
6622
6955
  then it will be looked up on the passed target.
6623
6956
  @param {Object} [args*] Optional arguments to pass to the timeout.
6624
6957
  @param {Number} spacing Number of milliseconds to space out requests.
6625
- @return {void}
6958
+ @return {Array} Timer information for use in cancelling, see `Ember.run.cancel`.
6626
6959
  */
6627
6960
  Ember.run.throttle = function() {
6628
6961
  return backburner.throttle.apply(backburner, arguments);
@@ -7133,6 +7466,9 @@ var Mixin, REQUIRED, Alias,
7133
7466
  guidFor = Ember.guidFor;
7134
7467
 
7135
7468
 
7469
+ var expandProperties = Ember.expandProperties;
7470
+
7471
+
7136
7472
  function mixinsMeta(obj) {
7137
7473
  var m = Ember.meta(obj, true), ret = m.mixins;
7138
7474
  if (!ret) {
@@ -7707,35 +8043,6 @@ Alias = function(methodName) {
7707
8043
  };
7708
8044
  Alias.prototype = new Ember.Descriptor();
7709
8045
 
7710
- /**
7711
- Makes a property or method available via an additional name.
7712
-
7713
- ```javascript
7714
- App.PaintSample = Ember.Object.extend({
7715
- color: 'red',
7716
- colour: Ember.alias('color'),
7717
- name: function() {
7718
- return "Zed";
7719
- },
7720
- moniker: Ember.alias("name")
7721
- });
7722
-
7723
- var paintSample = App.PaintSample.create()
7724
- paintSample.get('colour'); // 'red'
7725
- paintSample.moniker(); // 'Zed'
7726
- ```
7727
-
7728
- @method alias
7729
- @for Ember
7730
- @param {String} methodName name of the method or property to alias
7731
- @return {Ember.Descriptor}
7732
- @deprecated Use `Ember.aliasMethod` or `Ember.computed.alias` instead
7733
- */
7734
- Ember.alias = function(methodName) {
7735
- Ember.deprecate("Ember.alias is deprecated. Please use Ember.aliasMethod or Ember.computed.alias instead.");
7736
- return new Alias(methodName);
7737
- };
7738
-
7739
8046
  /**
7740
8047
  Makes a method available via an additional name.
7741
8048
 
@@ -7791,16 +8098,22 @@ Ember.observer = function() {
7791
8098
  var paths;
7792
8099
 
7793
8100
 
7794
- paths = a_slice.call(arguments, 0, -1);
8101
+ var addWatchedProperty = function (path) { paths.push(path); };
8102
+ var _paths = a_slice.call(arguments, 0, -1);
7795
8103
 
7796
8104
  if (typeof func !== "function") {
7797
8105
  // revert to old, soft-deprecated argument ordering
7798
8106
 
7799
8107
  func = arguments[0];
7800
- paths = a_slice.call(arguments, 1);
8108
+ _paths = a_slice.call(arguments, 1);
7801
8109
  }
7802
-
7803
8110
 
8111
+ paths = [];
8112
+
8113
+ for (var i=0; i<_paths.length; ++i) {
8114
+ expandProperties(_paths[i], addWatchedProperty);
8115
+ }
8116
+
7804
8117
  if (typeof func !== "function") {
7805
8118
  throw new Ember.Error("Ember.observer called without a function");
7806
8119
  }
@@ -7889,16 +8202,23 @@ Ember.beforeObserver = function() {
7889
8202
  var paths;
7890
8203
 
7891
8204
 
7892
- paths = a_slice.call(arguments, 0, -1);
8205
+ var addWatchedProperty = function(path) { paths.push(path); };
8206
+
8207
+ var _paths = a_slice.call(arguments, 0, -1);
7893
8208
 
7894
8209
  if (typeof func !== "function") {
7895
8210
  // revert to old, soft-deprecated argument ordering
7896
8211
 
7897
8212
  func = arguments[0];
7898
- paths = a_slice.call(arguments, 1);
8213
+ _paths = a_slice.call(arguments, 1);
7899
8214
  }
7900
-
7901
8215
 
8216
+ paths = [];
8217
+
8218
+ for (var i=0; i<_paths.length; ++i) {
8219
+ expandProperties(_paths[i], addWatchedProperty);
8220
+ }
8221
+
7902
8222
  if (typeof func !== "function") {
7903
8223
  throw new Ember.Error("Ember.beforeObserver called without a function");
7904
8224
  }
@@ -10135,6 +10455,7 @@ Ember.MODEL_FACTORY_INJECTIONS = false || !!Ember.ENV.MODEL_FACTORY_INJECTIONS;
10135
10455
  define("container",
10136
10456
  [],
10137
10457
  function() {
10458
+ "use strict";
10138
10459
 
10139
10460
  // A safe and simple inheriting object.
10140
10461
  function InheritingDict(parent) {
@@ -10256,7 +10577,8 @@ define("container",
10256
10577
 
10257
10578
  this.registry = new InheritingDict(parent && parent.registry);
10258
10579
  this.cache = new InheritingDict(parent && parent.cache);
10259
- this.factoryCache = new InheritingDict(parent && parent.cache);
10580
+ this.factoryCache = new InheritingDict(parent && parent.factoryCache);
10581
+ this.resolveCache = new InheritingDict(parent && parent.resolveCache);
10260
10582
  this.typeInjections = new InheritingDict(parent && parent.typeInjections);
10261
10583
  this.injections = {};
10262
10584
 
@@ -10377,9 +10699,7 @@ define("container",
10377
10699
  @param {Object} options
10378
10700
  */
10379
10701
  register: function(fullName, factory, options) {
10380
- if (fullName.indexOf(':') === -1) {
10381
- throw new TypeError("malformed fullName, expected: `type:name` got: " + fullName + "");
10382
- }
10702
+ validateFullName(fullName);
10383
10703
 
10384
10704
  if (factory === undefined) {
10385
10705
  throw new TypeError('Attempting to register an unknown factory: `' + fullName + '`');
@@ -10412,11 +10732,14 @@ define("container",
10412
10732
  @param {String} fullName
10413
10733
  */
10414
10734
  unregister: function(fullName) {
10735
+ validateFullName(fullName);
10736
+
10415
10737
  var normalizedName = this.normalize(fullName);
10416
10738
 
10417
10739
  this.registry.remove(normalizedName);
10418
10740
  this.cache.remove(normalizedName);
10419
10741
  this.factoryCache.remove(normalizedName);
10742
+ this.resolveCache.remove(normalizedName);
10420
10743
  this._options.remove(normalizedName);
10421
10744
  },
10422
10745
 
@@ -10453,7 +10776,18 @@ define("container",
10453
10776
  @return {Function} fullName's factory
10454
10777
  */
10455
10778
  resolve: function(fullName) {
10456
- return this.resolver(fullName) || this.registry.get(fullName);
10779
+ validateFullName(fullName);
10780
+
10781
+ var normalizedName = this.normalize(fullName);
10782
+ var cached = this.resolveCache.get(normalizedName);
10783
+
10784
+ if (cached) { return cached; }
10785
+
10786
+ var resolved = this.resolver(normalizedName) || this.registry.get(normalizedName);
10787
+
10788
+ this.resolveCache.set(normalizedName, resolved);
10789
+
10790
+ return resolved;
10457
10791
  },
10458
10792
 
10459
10793
  /**
@@ -10534,23 +10868,8 @@ define("container",
10534
10868
  @return {any}
10535
10869
  */
10536
10870
  lookup: function(fullName, options) {
10537
- fullName = this.normalize(fullName);
10538
-
10539
- options = options || {};
10540
-
10541
- if (this.cache.has(fullName) && options.singleton !== false) {
10542
- return this.cache.get(fullName);
10543
- }
10544
-
10545
- var value = instantiate(this, fullName);
10546
-
10547
- if (value === undefined) { return; }
10548
-
10549
- if (isSingleton(this, fullName) && options.singleton !== false) {
10550
- this.cache.set(fullName, value);
10551
- }
10552
-
10553
- return value;
10871
+ validateFullName(fullName);
10872
+ return lookup(this, this.normalize(fullName), options);
10554
10873
  },
10555
10874
 
10556
10875
  /**
@@ -10561,7 +10880,8 @@ define("container",
10561
10880
  @return {any}
10562
10881
  */
10563
10882
  lookupFactory: function(fullName) {
10564
- return factoryFor(this, fullName);
10883
+ validateFullName(fullName);
10884
+ return factoryFor(this, this.normalize(fullName));
10565
10885
  },
10566
10886
 
10567
10887
  /**
@@ -10573,11 +10893,8 @@ define("container",
10573
10893
  @return {Boolean}
10574
10894
  */
10575
10895
  has: function(fullName) {
10576
- if (this.cache.has(fullName)) {
10577
- return true;
10578
- }
10579
-
10580
- return !!this.resolve(fullName);
10896
+ validateFullName(fullName);
10897
+ return has(this, this.normalize(fullName));
10581
10898
  },
10582
10899
 
10583
10900
  /**
@@ -10658,6 +10975,7 @@ define("container",
10658
10975
  @param {String} fullName
10659
10976
  */
10660
10977
  typeInjection: function(type, property, fullName) {
10978
+ validateFullName(fullName);
10661
10979
  if (this.parent) { illegalChildOperation('typeInjection'); }
10662
10980
 
10663
10981
  addTypeInjection(this.typeInjections, type, property, fullName);
@@ -10707,14 +11025,20 @@ define("container",
10707
11025
  @param {String} property
10708
11026
  @param {String} injectionName
10709
11027
  */
10710
- injection: function(factoryName, property, injectionName) {
11028
+ injection: function(fullName, property, injectionName) {
10711
11029
  if (this.parent) { illegalChildOperation('injection'); }
10712
11030
 
10713
- if (factoryName.indexOf(':') === -1) {
10714
- return this.typeInjection(factoryName, property, injectionName);
11031
+ validateFullName(injectionName);
11032
+ var normalizedInjectionName = this.normalize(injectionName);
11033
+
11034
+ if (fullName.indexOf(':') === -1) {
11035
+ return this.typeInjection(fullName, property, normalizedInjectionName);
10715
11036
  }
10716
11037
 
10717
- addInjection(this.injections, factoryName, property, injectionName);
11038
+ validateFullName(fullName);
11039
+ var normalizedName = this.normalize(fullName);
11040
+
11041
+ addInjection(this.injections, normalizedName, property, normalizedInjectionName);
10718
11042
  },
10719
11043
 
10720
11044
 
@@ -10750,7 +11074,7 @@ define("container",
10750
11074
  factoryTypeInjection: function(type, property, fullName) {
10751
11075
  if (this.parent) { illegalChildOperation('factoryTypeInjection'); }
10752
11076
 
10753
- addTypeInjection(this.factoryTypeInjections, type, property, fullName);
11077
+ addTypeInjection(this.factoryTypeInjections, type, property, this.normalize(fullName));
10754
11078
  },
10755
11079
 
10756
11080
  /**
@@ -10802,14 +11126,21 @@ define("container",
10802
11126
  @param {String} property
10803
11127
  @param {String} injectionName
10804
11128
  */
10805
- factoryInjection: function(factoryName, property, injectionName) {
11129
+ factoryInjection: function(fullName, property, injectionName) {
10806
11130
  if (this.parent) { illegalChildOperation('injection'); }
10807
11131
 
10808
- if (factoryName.indexOf(':') === -1) {
10809
- return this.factoryTypeInjection(factoryName, property, injectionName);
11132
+ var normalizedName = this.normalize(fullName);
11133
+ var normalizedInjectionName = this.normalize(injectionName);
11134
+
11135
+ validateFullName(injectionName);
11136
+
11137
+ if (fullName.indexOf(':') === -1) {
11138
+ return this.factoryTypeInjection(normalizedName, property, normalizedInjectionName);
10810
11139
  }
10811
11140
 
10812
- addInjection(this.factoryInjections, factoryName, property, injectionName);
11141
+ validateFullName(fullName);
11142
+
11143
+ addInjection(this.factoryInjections, normalizedName, property, normalizedInjectionName);
10813
11144
  },
10814
11145
 
10815
11146
  /**
@@ -10819,7 +11150,6 @@ define("container",
10819
11150
  @method destroy
10820
11151
  */
10821
11152
  destroy: function() {
10822
-
10823
11153
  for (var i=0, l=this.children.length; i<l; i++) {
10824
11154
  this.children[i].destroy();
10825
11155
  }
@@ -10845,6 +11175,32 @@ define("container",
10845
11175
  }
10846
11176
  };
10847
11177
 
11178
+ function has(container, fullName){
11179
+ if (container.cache.has(fullName)) {
11180
+ return true;
11181
+ }
11182
+
11183
+ return !!container.resolve(fullName);
11184
+ }
11185
+
11186
+ function lookup(container, fullName, options) {
11187
+ options = options || {};
11188
+
11189
+ if (container.cache.has(fullName) && options.singleton !== false) {
11190
+ return container.cache.get(fullName);
11191
+ }
11192
+
11193
+ var value = instantiate(container, fullName);
11194
+
11195
+ if (value === undefined) { return; }
11196
+
11197
+ if (isSingleton(container, fullName) && options.singleton !== false) {
11198
+ container.cache.set(fullName, value);
11199
+ }
11200
+
11201
+ return value;
11202
+ }
11203
+
10848
11204
  function illegalChildOperation(operation) {
10849
11205
  throw new Error(operation + " is not currently supported on child containers");
10850
11206
  }
@@ -10860,14 +11216,14 @@ define("container",
10860
11216
 
10861
11217
  if (!injections) { return hash; }
10862
11218
 
10863
- var injection, lookup;
11219
+ var injection, injectable;
10864
11220
 
10865
11221
  for (var i=0, l=injections.length; i<l; i++) {
10866
11222
  injection = injections[i];
10867
- lookup = container.lookup(injection.fullName);
11223
+ injectable = lookup(container, injection.fullName);
10868
11224
 
10869
- if (lookup !== undefined) {
10870
- hash[injection.property] = lookup;
11225
+ if (injectable !== undefined) {
11226
+ hash[injection.property] = injectable;
10871
11227
  } else {
10872
11228
  throw new Error('Attempting to inject an unknown injection: `' + injection.fullName + '`');
10873
11229
  }
@@ -10892,7 +11248,7 @@ define("container",
10892
11248
  }
10893
11249
 
10894
11250
  function factoryFor(container, fullName) {
10895
- var name = container.normalize(fullName);
11251
+ var name = fullName;
10896
11252
  var factory = container.resolve(name);
10897
11253
  var injectedFactory;
10898
11254
  var cache = container.factoryCache;
@@ -11002,6 +11358,13 @@ define("container",
11002
11358
  });
11003
11359
  }
11004
11360
 
11361
+ var VALID_FULL_NAME_REGEXP = /^[^:]+.+:[^:]+$/;
11362
+ function validateFullName(fullName) {
11363
+ if (!VALID_FULL_NAME_REGEXP.test(fullName)) {
11364
+ throw new TypeError('Invalid Fullname, expected: `type:name` got: ' + fullName);
11365
+ }
11366
+ }
11367
+
11005
11368
  function addInjection(rules, factoryName, property, injectionName) {
11006
11369
  var injections = rules[factoryName] = rules[factoryName] || [];
11007
11370
  injections.push({ property: property, fullName: injectionName });
@@ -11196,39 +11559,6 @@ Ember.copy = function(obj, deep) {
11196
11559
  return _copy(obj, deep, deep ? [] : null, deep ? [] : null);
11197
11560
  };
11198
11561
 
11199
- /**
11200
- Convenience method to inspect an object. This method will attempt to
11201
- convert the object into a useful string description.
11202
-
11203
- It is a pretty simple implementation. If you want something more robust,
11204
- use something like JSDump: https://github.com/NV/jsDump
11205
-
11206
- @method inspect
11207
- @for Ember
11208
- @param {Object} obj The object you want to inspect.
11209
- @return {String} A description of the object
11210
- */
11211
- Ember.inspect = function(obj) {
11212
- var type = Ember.typeOf(obj);
11213
- if (type === 'array') {
11214
- return '[' + obj + ']';
11215
- }
11216
- if (type !== 'object') {
11217
- return obj + '';
11218
- }
11219
-
11220
- var v, ret = [];
11221
- for(var key in obj) {
11222
- if (obj.hasOwnProperty(key)) {
11223
- v = obj[key];
11224
- if (v === 'toString') { continue; } // ignore useless items
11225
- if (Ember.typeOf(v) === 'function') { v = "function() { ... }"; }
11226
- ret.push(key + ": " + v);
11227
- }
11228
- }
11229
- return "{" + ret.join(", ") + "}";
11230
- };
11231
-
11232
11562
  /**
11233
11563
  Compares two objects, returning true if they are logically equal. This is
11234
11564
  a deeper comparison than a simple triple equal. For sets it will compare the
@@ -11333,6 +11663,10 @@ var STRING_DECAMELIZE_REGEXP = (/([a-z\d])([A-Z])/g);
11333
11663
  var STRING_CAMELIZE_REGEXP = (/(\-|_|\.|\s)+(.)?/g);
11334
11664
  var STRING_UNDERSCORE_REGEXP_1 = (/([a-z\d])([A-Z]+)/g);
11335
11665
  var STRING_UNDERSCORE_REGEXP_2 = (/\-|\s+/g);
11666
+ var STRING_PARAMETERIZE_REGEXP_1 = (/[_|\/|\s]+/g);
11667
+ var STRING_PARAMETERIZE_REGEXP_2 = (/[^a-z0-9\-]+/gi);
11668
+ var STRING_PARAMETERIZE_REGEXP_3 = (/[\-]+/g);
11669
+ var STRING_PARAMETERIZE_REGEXP_4 = (/^-+|-+$/g);
11336
11670
 
11337
11671
  /**
11338
11672
  Defines the hash of localized strings for the current language. Used by
@@ -11571,6 +11905,54 @@ Ember.String = {
11571
11905
  }
11572
11906
  };
11573
11907
 
11908
+ if (Ember.FEATURES.isEnabled("string-humanize")) {
11909
+ /**
11910
+ Returns the Humanized form of a string
11911
+
11912
+ Replaces underscores with spaces, and capitializes first character
11913
+ of string. Also strips "_id" suffixes.
11914
+
11915
+ ```javascript
11916
+ 'first_name'.humanize() // 'First name'
11917
+ 'user_id'.humanize() // 'User'
11918
+ ```
11919
+
11920
+ @method humanize
11921
+ @param {String} str The string to humanize.
11922
+ @return {String} The humanized string.
11923
+ */
11924
+
11925
+ Ember.String.humanize = function(str) {
11926
+ return str.replace(/_id$/, '').
11927
+ replace(/_/g, ' ').
11928
+ replace(/^\w/g, function(s){
11929
+ return s.toUpperCase();
11930
+ });
11931
+ };
11932
+ }
11933
+
11934
+ if (Ember.FEATURES.isEnabled("string-parameterize")) {
11935
+ /**
11936
+ Transforms a string so that it may be used as part of a 'pretty' / SEO friendly URL.
11937
+
11938
+ ```javascript
11939
+ 'My favorite items.'.parameterize(); // 'my-favorite-items'
11940
+ 'action_name'.parameterize(); // 'action-name'
11941
+ '100 ways Ember.js is better than Angular.'.parameterize(); // '100-ways-emberjs-is-better-than-angular'
11942
+ ```
11943
+
11944
+ @method parameterize
11945
+ @param {String} str The string to parameterize.
11946
+ @return {String} the parameterized string.
11947
+ */
11948
+ Ember.String.parameterize = function(str) {
11949
+ return str.replace(STRING_PARAMETERIZE_REGEXP_1, '-') // replace underscores, slashes and spaces with separator
11950
+ .replace(STRING_PARAMETERIZE_REGEXP_2, '') // remove non-alphanumeric characters except the separator
11951
+ .replace(STRING_PARAMETERIZE_REGEXP_3, '-') // replace multiple occurring separators
11952
+ .replace(STRING_PARAMETERIZE_REGEXP_4, '') // trim leading and trailing separators
11953
+ .toLowerCase();
11954
+ };
11955
+ }
11574
11956
 
11575
11957
 
11576
11958
  })();
@@ -11595,6 +11977,13 @@ var fmt = Ember.String.fmt,
11595
11977
  capitalize = Ember.String.capitalize,
11596
11978
  classify = Ember.String.classify;
11597
11979
 
11980
+ if (Ember.FEATURES.isEnabled("string-humanize")) {
11981
+ var humanize = Ember.String.humanize;
11982
+ }
11983
+
11984
+ if (Ember.FEATURES.isEnabled("string-parameterize")) {
11985
+ var parameterize = Ember.String.parameterize;
11986
+ }
11598
11987
 
11599
11988
  if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.String) {
11600
11989
 
@@ -11688,7 +12077,30 @@ if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.String) {
11688
12077
  return capitalize(this);
11689
12078
  };
11690
12079
 
11691
-
12080
+ if (Ember.FEATURES.isEnabled("string-humanize")) {
12081
+ /**
12082
+ See [Ember.String.humanize](/api/classes/Ember.String.html#method_humanize).
12083
+
12084
+ @method humanize
12085
+ @for String
12086
+ */
12087
+ String.prototype.humanize = function() {
12088
+ return humanize(this);
12089
+ };
12090
+ }
12091
+
12092
+ if (Ember.FEATURES.isEnabled("string-parameterize")) {
12093
+ /**
12094
+ See [Ember.String.parameterize](/api/classes/Ember.String.html#method_parameterize).
12095
+
12096
+ @method parameterize
12097
+ @for String
12098
+ */
12099
+ String.prototype.parameterize = function() {
12100
+ return parameterize(this);
12101
+ };
12102
+ }
12103
+
11692
12104
  }
11693
12105
 
11694
12106
 
@@ -14062,7 +14474,7 @@ Ember.Enumerable = Ember.Mixin.create({
14062
14474
  var ret = initialValue;
14063
14475
 
14064
14476
  this.forEach(function(item, i) {
14065
- ret = callback.call(null, ret, item, i, this, reducerProperty);
14477
+ ret = callback(ret, item, i, this, reducerProperty);
14066
14478
  }, this);
14067
14479
 
14068
14480
  return ret;
@@ -14085,7 +14497,7 @@ Ember.Enumerable = Ember.Mixin.create({
14085
14497
  this.forEach(function(x, idx) {
14086
14498
  var method = x && x[methodName];
14087
14499
  if ('function' === typeof method) {
14088
- ret[idx] = args ? method.apply(x, args) : method.call(x);
14500
+ ret[idx] = args ? method.apply(x, args) : x[methodName]();
14089
14501
  }
14090
14502
  }, this);
14091
14503
 
@@ -14280,8 +14692,6 @@ Ember.Enumerable = Ember.Mixin.create({
14280
14692
  notify range observers.
14281
14693
 
14282
14694
  @method enumerableContentDidChange
14283
- @param {Number} [start] optional start offset for the content change.
14284
- For unordered enumerables, you should always pass -1.
14285
14695
  @param {Ember.Enumerable|Number} removing An enumerable of the objects to
14286
14696
  be removed or the number of items to be removed.
14287
14697
  @param {Ember.Enumerable|Number} adding An enumerable of the objects to
@@ -14491,7 +14901,7 @@ Ember.Array = Ember.Mixin.create(Ember.Enumerable, {
14491
14901
 
14492
14902
  @method slice
14493
14903
  @param {Integer} beginIndex (Optional) index to begin slicing from.
14494
- @param {Integer} endIndex (Optional) index to end the slice at.
14904
+ @param {Integer} endIndex (Optional) index to end the slice at (but not included).
14495
14905
  @return {Array} New array with specified slice
14496
14906
  */
14497
14907
  slice: function(beginIndex, endIndex) {
@@ -14642,7 +15052,7 @@ Ember.Array = Ember.Mixin.create(Ember.Enumerable, {
14642
15052
  Becomes true whenever the array currently has observers watching changes
14643
15053
  on the array.
14644
15054
 
14645
- @property Boolean
15055
+ @property {Boolean} hasArrayObservers
14646
15056
  */
14647
15057
  hasArrayObservers: Ember.computed(function() {
14648
15058
  return Ember.hasListeners(this, '@array:change') || Ember.hasListeners(this, '@array:before');
@@ -14792,6 +15202,9 @@ var e_get = Ember.get,
14792
15202
  arrayBracketPattern = /\.\[\]$/;
14793
15203
 
14794
15204
 
15205
+ var expandProperties = Ember.expandProperties;
15206
+
15207
+
14795
15208
  function get(obj, key) {
14796
15209
  if (key === '@this') {
14797
15210
  return obj;
@@ -15286,6 +15699,7 @@ function ReduceComputedProperty(options) {
15286
15699
  }, this);
15287
15700
  };
15288
15701
 
15702
+
15289
15703
  this.func = function (propertyName) {
15290
15704
  Ember.assert("Computed reduce values require at least one dependent key", cp._dependentKeys);
15291
15705
 
@@ -15373,10 +15787,13 @@ ReduceComputedProperty.prototype.property = function () {
15373
15787
  dependentArrayKey = match[1];
15374
15788
 
15375
15789
 
15376
- itemPropertyKey = match[2];
15377
- cp.itemPropertyKey(dependentArrayKey, itemPropertyKey);
15378
-
15379
- propertyArgs.add(dependentArrayKey);
15790
+ var itemPropertyKeyPattern = match[2],
15791
+ addItemPropertyKey = function (itemPropertyKey) {
15792
+ cp.itemPropertyKey(dependentArrayKey, itemPropertyKey);
15793
+ };
15794
+
15795
+ expandProperties(itemPropertyKeyPattern, addItemPropertyKey);
15796
+ propertyArgs.add(dependentArrayKey);
15380
15797
  } else {
15381
15798
  propertyArgs.add(dependentKey);
15382
15799
  }
@@ -15486,7 +15903,7 @@ ReduceComputedProperty.prototype.property = function () {
15486
15903
 
15487
15904
  ```javascript
15488
15905
  Ember.computed.max = function (dependentKey) {
15489
- return Ember.reduceComputed.call(null, dependentKey, {
15906
+ return Ember.reduceComputed(dependentKey, {
15490
15907
  initialValue: -Infinity,
15491
15908
 
15492
15909
  addedItem: function (accumulatedValue, item, changeMeta, instanceMeta) {
@@ -15795,6 +16212,30 @@ var get = Ember.get,
15795
16212
  map = Ember.EnumerableUtils.map,
15796
16213
  SearchProxy;
15797
16214
 
16215
+ /**
16216
+ A computed property that returns the sum of the value
16217
+ in the dependent array.
16218
+
16219
+ @method computed.sum
16220
+ @for Ember
16221
+ @param {String} dependentKey
16222
+ @return {Ember.ComputedProperty} computes the sum of all values in the dependentKey's array
16223
+ */
16224
+
16225
+ Ember.computed.sum = function(dependentKey){
16226
+ return Ember.reduceComputed(dependentKey, {
16227
+ initialValue: 0,
16228
+
16229
+ addedItem: function(accumulatedValue, item, changeMeta, instanceMeta){
16230
+ return accumulatedValue + item;
16231
+ },
16232
+
16233
+ removedItem: function(accumulatedValue, item, changeMeta, instanceMeta){
16234
+ return accumulatedValue - item;
16235
+ }
16236
+ });
16237
+ };
16238
+
15798
16239
  /**
15799
16240
  A computed property that calculates the maximum value in the
15800
16241
  dependent array. This will return `-Infinity` when the dependent
@@ -15828,7 +16269,7 @@ var get = Ember.get,
15828
16269
  @return {Ember.ComputedProperty} computes the largest value in the dependentKey's array
15829
16270
  */
15830
16271
  Ember.computed.max = function (dependentKey) {
15831
- return Ember.reduceComputed.call(null, dependentKey, {
16272
+ return Ember.reduceComputed(dependentKey, {
15832
16273
  initialValue: -Infinity,
15833
16274
 
15834
16275
  addedItem: function (accumulatedValue, item, changeMeta, instanceMeta) {
@@ -15876,7 +16317,7 @@ Ember.computed.max = function (dependentKey) {
15876
16317
  @return {Ember.ComputedProperty} computes the smallest value in the dependentKey's array
15877
16318
  */
15878
16319
  Ember.computed.min = function (dependentKey) {
15879
- return Ember.reduceComputed.call(null, dependentKey, {
16320
+ return Ember.reduceComputed(dependentKey, {
15880
16321
  initialValue: Infinity,
15881
16322
 
15882
16323
  addedItem: function (accumulatedValue, item, changeMeta, instanceMeta) {
@@ -16161,7 +16602,7 @@ Ember.computed.union = Ember.computed.uniq;
16161
16602
 
16162
16603
  /**
16163
16604
  A computed property which returns a new array with all the duplicated
16164
- elements from two or more dependeny arrays.
16605
+ elements from two or more dependent arrays.
16165
16606
 
16166
16607
  Example
16167
16608
 
@@ -16267,7 +16708,7 @@ Ember.computed.setDiff = function (setAProperty, setBProperty) {
16267
16708
  if (arguments.length !== 2) {
16268
16709
  throw new Ember.Error("setDiff requires exactly two dependent arrays.");
16269
16710
  }
16270
- return Ember.arrayComputed.call(null, setAProperty, setBProperty, {
16711
+ return Ember.arrayComputed(setAProperty, setBProperty, {
16271
16712
  addedItem: function (array, item, changeMeta, instanceMeta) {
16272
16713
  var setA = get(this, setAProperty),
16273
16714
  setB = get(this, setBProperty);
@@ -16469,7 +16910,7 @@ Ember.computed.sort = function (itemsKey, sortDefinition) {
16469
16910
  };
16470
16911
  }
16471
16912
 
16472
- return Ember.arrayComputed.call(null, itemsKey, {
16913
+ return Ember.arrayComputed(itemsKey, {
16473
16914
  initialize: initFn,
16474
16915
 
16475
16916
  addedItem: function (array, item, changeMeta, instanceMeta) {
@@ -16533,6 +16974,9 @@ Ember.RSVP.on('error', Ember.RSVP.onerrorDefault);
16533
16974
  var a_slice = Array.prototype.slice;
16534
16975
 
16535
16976
 
16977
+ var expandProperties = Ember.expandProperties;
16978
+
16979
+
16536
16980
  if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Function) {
16537
16981
 
16538
16982
  /**
@@ -16629,9 +17073,15 @@ if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Function) {
16629
17073
  */
16630
17074
  Function.prototype.observes = function() {
16631
17075
 
16632
- this.__ember_observes__ = a_slice.call(arguments);
16633
-
17076
+ var addWatchedProperty = function (obs) { watched.push(obs); };
17077
+ var watched = [];
17078
+
17079
+ for (var i=0; i<arguments.length; ++i) {
17080
+ expandProperties(arguments[i], addWatchedProperty);
17081
+ }
16634
17082
 
17083
+ this.__ember_observes__ = watched;
17084
+
16635
17085
  return this;
16636
17086
  };
16637
17087
 
@@ -16694,9 +17144,15 @@ if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.Function) {
16694
17144
  */
16695
17145
  Function.prototype.observesBefore = function() {
16696
17146
 
16697
- this.__ember_observesBefore__ = a_slice.call(arguments);
16698
-
17147
+ var addWatchedProperty = function (obs) { watched.push(obs); };
17148
+ var watched = [];
17149
+
17150
+ for (var i=0; i<arguments.length; ++i) {
17151
+ expandProperties(arguments[i], addWatchedProperty);
17152
+ }
16699
17153
 
17154
+ this.__ember_observesBefore__ = watched;
17155
+
16700
17156
  return this;
16701
17157
  };
16702
17158
 
@@ -17899,6 +18355,8 @@ Ember.ActionHandler = Ember.Mixin.create({
17899
18355
  var hashName;
17900
18356
 
17901
18357
  if (!props._actions) {
18358
+ Ember.assert(this + " 'actions' should not be a function", typeof(props.actions) !== 'function');
18359
+
17902
18360
  if (typeOf(props.actions) === 'object') {
17903
18361
  hashName = 'actions';
17904
18362
  } else if (typeOf(props.events) === 'object') {
@@ -17945,8 +18403,6 @@ Ember.ActionHandler = Ember.Mixin.create({
17945
18403
 
17946
18404
  (function() {
17947
18405
  var set = Ember.set, get = Ember.get,
17948
- resolve = Ember.RSVP.resolve,
17949
- rethrow = Ember.RSVP.rethrow,
17950
18406
  not = Ember.computed.not,
17951
18407
  or = Ember.computed.or;
17952
18408
 
@@ -17955,14 +18411,15 @@ var set = Ember.set, get = Ember.get,
17955
18411
  @submodule ember-runtime
17956
18412
  */
17957
18413
 
17958
- function observePromise(proxy, promise) {
17959
- promise.then(function(value) {
18414
+ function tap(proxy, promise) {
18415
+ return promise.then(function(value) {
17960
18416
  set(proxy, 'isFulfilled', true);
17961
18417
  set(proxy, 'content', value);
18418
+ return value;
17962
18419
  }, function(reason) {
17963
18420
  set(proxy, 'isRejected', true);
17964
18421
  set(proxy, 'reason', reason);
17965
- // don't re-throw, as we are merely observing
18422
+ throw reason;
17966
18423
  }, "Ember: PromiseProxy");
17967
18424
  }
17968
18425
 
@@ -18091,9 +18548,7 @@ Ember.PromiseProxyMixin = Ember.Mixin.create({
18091
18548
  */
18092
18549
  promise: Ember.computed(function(key, promise) {
18093
18550
  if (arguments.length === 2) {
18094
- promise = resolve(promise);
18095
- observePromise(this, promise);
18096
- return promise.then(); // fork the promise.
18551
+ return tap(this, promise);
18097
18552
  } else {
18098
18553
  throw new Ember.Error("PromiseProxy's promise must be set");
18099
18554
  }