ember-source 1.1.3 → 1.2.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
@@ -1,6 +1,16 @@
1
1
  (function() {
2
2
  var Ember = { assert: function() {}, FEATURES: { isEnabled: function() {} } };
3
- // Version: 1.1.3
3
+ // ==========================================================================
4
+ // Project: Ember - JavaScript Application Framework
5
+ // Copyright: Copyright 2011-2013 Tilde Inc. and contributors
6
+ // Portions Copyright 2006-2011 Strobe Inc.
7
+ // Portions Copyright 2008-2011 Apple Inc. All rights reserved.
8
+ // License: Licensed under MIT license
9
+ // See https://raw.github.com/emberjs/ember.js/master/LICENSE
10
+ // ==========================================================================
11
+
12
+
13
+ // Version: 1.2.0-beta.1
4
14
 
5
15
  (function() {
6
16
  /*global __fail__*/
@@ -1,4 +1,14 @@
1
- // Version: 1.1.3
1
+ // ==========================================================================
2
+ // Project: Ember - JavaScript Application Framework
3
+ // Copyright: Copyright 2011-2013 Tilde Inc. and contributors
4
+ // Portions Copyright 2006-2011 Strobe Inc.
5
+ // Portions Copyright 2008-2011 Apple Inc. All rights reserved.
6
+ // License: Licensed under MIT license
7
+ // See https://raw.github.com/emberjs/ember.js/master/LICENSE
8
+ // ==========================================================================
9
+
10
+
11
+ // Version: 1.2.0-beta.1
2
12
 
3
13
  (function() {
4
14
  /*global __fail__*/
@@ -174,7 +184,17 @@ if (!Ember.testing) {
174
184
 
175
185
  })();
176
186
 
177
- // Version: 1.1.3
187
+ // ==========================================================================
188
+ // Project: Ember - JavaScript Application Framework
189
+ // Copyright: Copyright 2011-2013 Tilde Inc. and contributors
190
+ // Portions Copyright 2006-2011 Strobe Inc.
191
+ // Portions Copyright 2008-2011 Apple Inc. All rights reserved.
192
+ // License: Licensed under MIT license
193
+ // See https://raw.github.com/emberjs/ember.js/master/LICENSE
194
+ // ==========================================================================
195
+
196
+
197
+ // Version: 1.2.0-beta.1
178
198
 
179
199
  (function() {
180
200
  var define, requireModule;
@@ -239,7 +259,7 @@ var define, requireModule;
239
259
 
240
260
  @class Ember
241
261
  @static
242
- @version 1.1.3
262
+ @version 1.2.0-beta.1
243
263
  */
244
264
 
245
265
  if ('undefined' === typeof Ember) {
@@ -266,10 +286,10 @@ Ember.toString = function() { return "Ember"; };
266
286
  /**
267
287
  @property VERSION
268
288
  @type String
269
- @default '1.1.3'
289
+ @default '1.2.0-beta.1'
270
290
  @final
271
291
  */
272
- Ember.VERSION = '1.1.3';
292
+ Ember.VERSION = '1.2.0-beta.1';
273
293
 
274
294
  /**
275
295
  Standard environmental variables. You can define these in a global `ENV`
@@ -297,22 +317,27 @@ Ember.config = Ember.config || {};
297
317
  /**
298
318
  Hash of enabled Canary features. Add to before creating your application.
299
319
 
320
+ You can also define `ENV.FEATURES` if you need to enable features flagged at runtime.
321
+
300
322
  @property FEATURES
301
323
  @type Hash
302
324
  */
303
325
 
304
- Ember.FEATURES = {};
326
+ Ember.FEATURES = Ember.ENV.FEATURES || {};
305
327
 
306
328
  /**
307
329
  Test that a feature is enabled. Parsed by Ember's build tools to leave
308
330
  experimental features out of beta/stable builds.
309
331
 
332
+ You can define an `ENV.ENABLE_ALL_FEATURES` config to force all features to
333
+ be enabled.
334
+
310
335
  @method isEnabled
311
336
  @param {string} feature
312
337
  */
313
338
 
314
339
  Ember.FEATURES.isEnabled = function(feature) {
315
- return Ember.FEATURES[feature];
340
+ return Ember.ENV.ENABLE_ALL_FEATURES || Ember.FEATURES[feature];
316
341
  };
317
342
 
318
343
  // ..........................................................
@@ -396,189 +421,6 @@ if ('undefined' === typeof Ember.deprecateFunc) {
396
421
  */
397
422
  Ember.uuid = 0;
398
423
 
399
- // ..........................................................
400
- // LOGGER
401
- //
402
-
403
- function consoleMethod(name) {
404
- var consoleObj;
405
- if (imports.console) {
406
- consoleObj = imports.console;
407
- } else if (typeof console !== 'undefined') {
408
- consoleObj = console;
409
- }
410
-
411
- var method = typeof consoleObj === 'object' ? consoleObj[name] : null;
412
-
413
- if (method) {
414
- // Older IE doesn't support apply, but Chrome needs it
415
- if (method.apply) {
416
- return function() {
417
- method.apply(consoleObj, arguments);
418
- };
419
- } else {
420
- return function() {
421
- var message = Array.prototype.join.call(arguments, ', ');
422
- method(message);
423
- };
424
- }
425
- }
426
- }
427
-
428
- function assertPolyfill(test, message) {
429
- if (!test) {
430
- try {
431
- // attempt to preserve the stack
432
- throw new Error("assertion failed: " + message);
433
- } catch(error) {
434
- setTimeout(function() {
435
- throw error;
436
- }, 0);
437
- }
438
- }
439
- }
440
-
441
- /**
442
- Inside Ember-Metal, simply uses the methods from `imports.console`.
443
- Override this to provide more robust logging functionality.
444
-
445
- @class Logger
446
- @namespace Ember
447
- */
448
- Ember.Logger = {
449
- /**
450
- Logs the arguments to the console.
451
- You can pass as many arguments as you want and they will be joined together with a space.
452
-
453
- ```javascript
454
- var foo = 1;
455
- Ember.Logger.log('log value of foo:', foo); // "log value of foo: 1" will be printed to the console
456
- ```
457
-
458
- @method log
459
- @for Ember.Logger
460
- @param {*} arguments
461
- */
462
- log: consoleMethod('log') || Ember.K,
463
- /**
464
- Prints the arguments to the console with a warning icon.
465
- You can pass as many arguments as you want and they will be joined together with a space.
466
-
467
- ```javascript
468
- Ember.Logger.warn('Something happened!'); // "Something happened!" will be printed to the console with a warning icon.
469
- ```
470
-
471
- @method warn
472
- @for Ember.Logger
473
- @param {*} arguments
474
- */
475
- warn: consoleMethod('warn') || Ember.K,
476
- /**
477
- Prints the arguments to the console with an error icon, red text and a stack race.
478
- You can pass as many arguments as you want and they will be joined together with a space.
479
-
480
- ```javascript
481
- Ember.Logger.error('Danger! Danger!'); // "Danger! Danger!" will be printed to the console in red text.
482
- ```
483
-
484
- @method error
485
- @for Ember.Logger
486
- @param {*} arguments
487
- */
488
- error: consoleMethod('error') || Ember.K,
489
- /**
490
- Logs the arguments to the console.
491
- You can pass as many arguments as you want and they will be joined together with a space.
492
-
493
- ```javascript
494
- var foo = 1;
495
- Ember.Logger.info('log value of foo:', foo); // "log value of foo: 1" will be printed to the console
496
- ```
497
-
498
- @method info
499
- @for Ember.Logger
500
- @param {*} arguments
501
- */
502
- info: consoleMethod('info') || Ember.K,
503
- /**
504
- Logs the arguments to the console in blue text.
505
- You can pass as many arguments as you want and they will be joined together with a space.
506
-
507
- ```javascript
508
- var foo = 1;
509
- Ember.Logger.debug('log value of foo:', foo); // "log value of foo: 1" will be printed to the console
510
- ```
511
-
512
- @method debug
513
- @for Ember.Logger
514
- @param {*} arguments
515
- */
516
- debug: consoleMethod('debug') || consoleMethod('info') || Ember.K,
517
- /**
518
-
519
- If the value passed into Ember.Logger.assert is not truthy it will throw an error with a stack trace.
520
-
521
- ```javascript
522
- Ember.Logger.assert(true); // undefined
523
- Ember.Logger.assert(true === false); // Throws an Assertion failed error.
524
- ```
525
-
526
- @method assert
527
- @for Ember.Logger
528
- @param {Boolean} bool Value to test
529
- */
530
- assert: consoleMethod('assert') || assertPolyfill
531
- };
532
-
533
-
534
- // ..........................................................
535
- // ERROR HANDLING
536
- //
537
-
538
- /**
539
- A function may be assigned to `Ember.onerror` to be called when Ember
540
- internals encounter an error. This is useful for specialized error handling
541
- and reporting code.
542
-
543
- ```javascript
544
- Ember.onerror = function(error) {
545
- Em.$.ajax('/report-error', 'POST', {
546
- stack: error.stack,
547
- otherInformation: 'whatever app state you want to provide'
548
- });
549
- };
550
- ```
551
-
552
- @event onerror
553
- @for Ember
554
- @param {Exception} error the error object
555
- */
556
- Ember.onerror = null;
557
-
558
- /**
559
- @private
560
-
561
- Wrap code block in a try/catch if `Ember.onerror` is set.
562
-
563
- @method handleErrors
564
- @for Ember
565
- @param {Function} func
566
- @param [context]
567
- */
568
- Ember.handleErrors = function(func, context) {
569
- // Unfortunately in some browsers we lose the backtrace if we rethrow the existing error,
570
- // so in the event that we don't have an `onerror` handler we don't wrap in a try/catch
571
- if ('function' === typeof Ember.onerror) {
572
- try {
573
- return func.call(context || this);
574
- } catch (error) {
575
- Ember.onerror(error);
576
- }
577
- } else {
578
- return func.call(context || this);
579
- }
580
- };
581
-
582
424
  /**
583
425
  Merge the contents of two objects together into the first object.
584
426
 
@@ -926,11 +768,93 @@ if (Ember.SHIM_ES5) {
926
768
 
927
769
 
928
770
 
771
+ (function() {
772
+ var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack'];
773
+
774
+ /**
775
+ A subclass of the JavaScript Error object for use in Ember.
776
+
777
+ @class Error
778
+ @namespace Ember
779
+ @extends Error
780
+ @constructor
781
+ */
782
+ Ember.Error = function() {
783
+ var tmp = Error.apply(this, arguments);
784
+
785
+ // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work.
786
+ for (var idx = 0; idx < errorProps.length; idx++) {
787
+ this[errorProps[idx]] = tmp[errorProps[idx]];
788
+ }
789
+ };
790
+
791
+ Ember.Error.prototype = Ember.create(Error.prototype);
792
+
793
+ // ..........................................................
794
+ // ERROR HANDLING
795
+ //
796
+
797
+ /**
798
+ A function may be assigned to `Ember.onerror` to be called when Ember
799
+ internals encounter an error. This is useful for specialized error handling
800
+ and reporting code.
801
+
802
+ ```javascript
803
+ Ember.onerror = function(error) {
804
+ Em.$.ajax('/report-error', 'POST', {
805
+ stack: error.stack,
806
+ otherInformation: 'whatever app state you want to provide'
807
+ });
808
+ };
809
+ ```
810
+
811
+ @event onerror
812
+ @for Ember
813
+ @param {Exception} error the error object
814
+ */
815
+ Ember.onerror = null;
816
+
817
+ /**
818
+ @private
819
+
820
+ Wrap code block in a try/catch if `Ember.onerror` is set.
821
+
822
+ @method handleErrors
823
+ @for Ember
824
+ @param {Function} func
825
+ @param [context]
826
+ */
827
+ Ember.handleErrors = function(func, context) {
828
+ // Unfortunately in some browsers we lose the backtrace if we rethrow the existing error,
829
+ // so in the event that we don't have an `onerror` handler we don't wrap in a try/catch
830
+ if ('function' === typeof Ember.onerror) {
831
+ try {
832
+ return func.call(context || this);
833
+ } catch (error) {
834
+ Ember.onerror(error);
835
+ }
836
+ } else {
837
+ return func.call(context || this);
838
+ }
839
+ };
840
+
841
+ })();
842
+
843
+
844
+
929
845
  (function() {
930
846
  /**
931
847
  @module ember-metal
932
848
  */
933
849
 
850
+ /**
851
+ @private
852
+
853
+ Prefix used for guids through out Ember.
854
+
855
+ */
856
+ Ember.GUID_PREFIX = 'ember';
857
+
934
858
 
935
859
  var o_defineProperty = Ember.platform.defineProperty,
936
860
  o_create = Ember.create,
@@ -985,13 +909,13 @@ var GUID_DESC = {
985
909
  @return {String} the guid
986
910
  */
987
911
  Ember.generateGuid = function generateGuid(obj, prefix) {
988
- if (!prefix) prefix = 'ember';
912
+ if (!prefix) prefix = Ember.GUID_PREFIX;
989
913
  var ret = (prefix + (uuid++));
990
914
  if (obj) {
991
915
  GUID_DESC.value = ret;
992
916
  o_defineProperty(obj, GUID_KEY, GUID_DESC);
993
917
  }
994
- return ret ;
918
+ return ret;
995
919
  };
996
920
 
997
921
  /**
@@ -1989,7 +1913,7 @@ var normalizeTuple = Ember.normalizeTuple = function(target, path) {
1989
1913
  }
1990
1914
 
1991
1915
  // must return some kind of path to be valid else other things will break.
1992
- if (!path || path.length===0) throw new Error('Invalid Path');
1916
+ if (!path || path.length===0) throw new Ember.Error('Invalid Path');
1993
1917
 
1994
1918
  return [ target, path ];
1995
1919
  };
@@ -2030,7 +1954,6 @@ Ember.getWithDefault = function(root, key, defaultValue) {
2030
1954
 
2031
1955
 
2032
1956
  Ember.get = get;
2033
- Ember.getPath = Ember.deprecateFunc('getPath is deprecated since get now supports paths', Ember.get);
2034
1957
 
2035
1958
  })();
2036
1959
 
@@ -2857,19 +2780,18 @@ function setPath(root, path, value, tolerant) {
2857
2780
  }
2858
2781
 
2859
2782
  if (!keyName || keyName.length === 0) {
2860
- throw new Error('You passed an empty path');
2783
+ throw new Ember.Error('You passed an empty path');
2861
2784
  }
2862
2785
 
2863
2786
  if (!root) {
2864
2787
  if (tolerant) { return; }
2865
- else { throw new Error('Object in path '+path+' could not be found or was destroyed.'); }
2788
+ else { throw new Ember.Error('Object in path '+path+' could not be found or was destroyed.'); }
2866
2789
  }
2867
2790
 
2868
2791
  return set(root, keyName, value);
2869
2792
  }
2870
2793
 
2871
2794
  Ember.set = set;
2872
- Ember.setPath = Ember.deprecateFunc('setPath is deprecated since set now supports paths', Ember.set);
2873
2795
 
2874
2796
  /**
2875
2797
  Error-tolerant form of `Ember.set`. Will not blow up if any part of the
@@ -2887,7 +2809,6 @@ Ember.setPath = Ember.deprecateFunc('setPath is deprecated since set now support
2887
2809
  Ember.trySet = function(root, path, value) {
2888
2810
  return set(root, path, value, true);
2889
2811
  };
2890
- Ember.trySetPath = Ember.deprecateFunc('trySetPath has been renamed to trySet', Ember.trySet);
2891
2812
 
2892
2813
  })();
2893
2814
 
@@ -3221,53 +3142,189 @@ var MapWithDefault = Ember.MapWithDefault = function(options) {
3221
3142
  this.defaultValue = options.defaultValue;
3222
3143
  };
3223
3144
 
3224
- /**
3225
- @method create
3226
- @static
3227
- @param [options]
3228
- @param {*} [options.defaultValue]
3229
- @return {Ember.MapWithDefault|Ember.Map} If options are passed, returns
3230
- `Ember.MapWithDefault` otherwise returns `Ember.Map`
3231
- */
3232
- MapWithDefault.create = function(options) {
3233
- if (options) {
3234
- return new MapWithDefault(options);
3235
- } else {
3236
- return new Map();
3237
- }
3238
- };
3145
+ /**
3146
+ @method create
3147
+ @static
3148
+ @param [options]
3149
+ @param {*} [options.defaultValue]
3150
+ @return {Ember.MapWithDefault|Ember.Map} If options are passed, returns
3151
+ `Ember.MapWithDefault` otherwise returns `Ember.Map`
3152
+ */
3153
+ MapWithDefault.create = function(options) {
3154
+ if (options) {
3155
+ return new MapWithDefault(options);
3156
+ } else {
3157
+ return new Map();
3158
+ }
3159
+ };
3160
+
3161
+ MapWithDefault.prototype = Ember.create(Map.prototype);
3162
+
3163
+ /**
3164
+ Retrieve the value associated with a given key.
3165
+
3166
+ @method get
3167
+ @param {*} key
3168
+ @return {*} the value associated with the key, or the default value
3169
+ */
3170
+ MapWithDefault.prototype.get = function(key) {
3171
+ var hasValue = this.has(key);
3172
+
3173
+ if (hasValue) {
3174
+ return Map.prototype.get.call(this, key);
3175
+ } else {
3176
+ var defaultValue = this.defaultValue(key);
3177
+ this.set(key, defaultValue);
3178
+ return defaultValue;
3179
+ }
3180
+ };
3181
+
3182
+ /**
3183
+ @method copy
3184
+ @return {Ember.MapWithDefault}
3185
+ */
3186
+ MapWithDefault.prototype.copy = function() {
3187
+ return copyMap(this, new MapWithDefault({
3188
+ defaultValue: this.defaultValue
3189
+ }));
3190
+ };
3191
+
3192
+ })();
3193
+
3194
+
3195
+
3196
+ (function() {
3197
+ function consoleMethod(name) {
3198
+ var consoleObj;
3199
+ if (Ember.imports.console) {
3200
+ consoleObj = Ember.imports.console;
3201
+ } else if (typeof console !== 'undefined') {
3202
+ consoleObj = console;
3203
+ }
3204
+
3205
+ var method = typeof consoleObj === 'object' ? consoleObj[name] : null;
3206
+
3207
+ if (method) {
3208
+ // Older IE doesn't support apply, but Chrome needs it
3209
+ if (method.apply) {
3210
+ return function() {
3211
+ method.apply(consoleObj, arguments);
3212
+ };
3213
+ } else {
3214
+ return function() {
3215
+ var message = Array.prototype.join.call(arguments, ', ');
3216
+ method(message);
3217
+ };
3218
+ }
3219
+ }
3220
+ }
3221
+
3222
+ function assertPolyfill(test, message) {
3223
+ if (!test) {
3224
+ try {
3225
+ // attempt to preserve the stack
3226
+ throw new Ember.Error("assertion failed: " + message);
3227
+ } catch(error) {
3228
+ setTimeout(function() {
3229
+ throw error;
3230
+ }, 0);
3231
+ }
3232
+ }
3233
+ }
3234
+
3235
+ /**
3236
+ Inside Ember-Metal, simply uses the methods from `imports.console`.
3237
+ Override this to provide more robust logging functionality.
3238
+
3239
+ @class Logger
3240
+ @namespace Ember
3241
+ */
3242
+ Ember.Logger = {
3243
+ /**
3244
+ Logs the arguments to the console.
3245
+ You can pass as many arguments as you want and they will be joined together with a space.
3246
+
3247
+ ```javascript
3248
+ var foo = 1;
3249
+ Ember.Logger.log('log value of foo:', foo); // "log value of foo: 1" will be printed to the console
3250
+ ```
3251
+
3252
+ @method log
3253
+ @for Ember.Logger
3254
+ @param {*} arguments
3255
+ */
3256
+ log: consoleMethod('log') || Ember.K,
3257
+ /**
3258
+ Prints the arguments to the console with a warning icon.
3259
+ You can pass as many arguments as you want and they will be joined together with a space.
3260
+
3261
+ ```javascript
3262
+ Ember.Logger.warn('Something happened!'); // "Something happened!" will be printed to the console with a warning icon.
3263
+ ```
3264
+
3265
+ @method warn
3266
+ @for Ember.Logger
3267
+ @param {*} arguments
3268
+ */
3269
+ warn: consoleMethod('warn') || Ember.K,
3270
+ /**
3271
+ Prints the arguments to the console with an error icon, red text and a stack race.
3272
+ You can pass as many arguments as you want and they will be joined together with a space.
3273
+
3274
+ ```javascript
3275
+ Ember.Logger.error('Danger! Danger!'); // "Danger! Danger!" will be printed to the console in red text.
3276
+ ```
3277
+
3278
+ @method error
3279
+ @for Ember.Logger
3280
+ @param {*} arguments
3281
+ */
3282
+ error: consoleMethod('error') || Ember.K,
3283
+ /**
3284
+ Logs the arguments to the console.
3285
+ You can pass as many arguments as you want and they will be joined together with a space.
3286
+
3287
+ ```javascript
3288
+ var foo = 1;
3289
+ Ember.Logger.info('log value of foo:', foo); // "log value of foo: 1" will be printed to the console
3290
+ ```
3239
3291
 
3240
- MapWithDefault.prototype = Ember.create(Map.prototype);
3292
+ @method info
3293
+ @for Ember.Logger
3294
+ @param {*} arguments
3295
+ */
3296
+ info: consoleMethod('info') || Ember.K,
3297
+ /**
3298
+ Logs the arguments to the console in blue text.
3299
+ You can pass as many arguments as you want and they will be joined together with a space.
3241
3300
 
3242
- /**
3243
- Retrieve the value associated with a given key.
3301
+ ```javascript
3302
+ var foo = 1;
3303
+ Ember.Logger.debug('log value of foo:', foo); // "log value of foo: 1" will be printed to the console
3304
+ ```
3244
3305
 
3245
- @method get
3246
- @param {*} key
3247
- @return {*} the value associated with the key, or the default value
3248
- */
3249
- MapWithDefault.prototype.get = function(key) {
3250
- var hasValue = this.has(key);
3306
+ @method debug
3307
+ @for Ember.Logger
3308
+ @param {*} arguments
3309
+ */
3310
+ debug: consoleMethod('debug') || consoleMethod('info') || Ember.K,
3311
+ /**
3251
3312
 
3252
- if (hasValue) {
3253
- return Map.prototype.get.call(this, key);
3254
- } else {
3255
- var defaultValue = this.defaultValue(key);
3256
- this.set(key, defaultValue);
3257
- return defaultValue;
3258
- }
3259
- };
3313
+ If the value passed into Ember.Logger.assert is not truthy it will throw an error with a stack trace.
3260
3314
 
3261
- /**
3262
- @method copy
3263
- @return {Ember.MapWithDefault}
3264
- */
3265
- MapWithDefault.prototype.copy = function() {
3266
- return copyMap(this, new MapWithDefault({
3267
- defaultValue: this.defaultValue
3268
- }));
3315
+ ```javascript
3316
+ Ember.Logger.assert(true); // undefined
3317
+ Ember.Logger.assert(true === false); // Throws an Assertion failed error.
3318
+ ```
3319
+
3320
+ @method assert
3321
+ @for Ember.Logger
3322
+ @param {Boolean} bool Value to test
3323
+ */
3324
+ assert: consoleMethod('assert') || assertPolyfill
3269
3325
  };
3270
3326
 
3327
+
3271
3328
  })();
3272
3329
 
3273
3330
 
@@ -3897,6 +3954,45 @@ Ember.finishChains = function(obj) {
3897
3954
 
3898
3955
 
3899
3956
 
3957
+ (function() {
3958
+ /**
3959
+ @module ember-metal
3960
+ */
3961
+
3962
+ var forEach = Ember.EnumerableUtils.forEach,
3963
+ IS_BRACE_EXPANSION = /^\{([^.]*)\}$/;
3964
+
3965
+ /**
3966
+ Expands `pattern`, invoking `callback` for each expansion.
3967
+
3968
+ The only pattern supported is brace-expansion, anything else will be passed
3969
+ once to `callback` directly. Furthermore, brace-expansion is only applied to
3970
+ the entire pattern, not to substrings.
3971
+
3972
+ Example
3973
+ ```js
3974
+ function echo(arg){ console.log(arg); }
3975
+
3976
+ Ember.expandProperties('foo.bar', echo); //=> 'foo.bar'
3977
+ Ember.expandProperties('{foo,bar}', echo); //=> 'foo', 'bar'
3978
+ Ember.expandProperties('foo.{bar,baz}', echo); //=> 'foo.{bar,baz}'
3979
+ ```
3980
+
3981
+ @method
3982
+ @private
3983
+ @param {string} pattern The property pattern to expand.
3984
+ @param {function} callback The callback to invoke. It is invoked once per
3985
+ expansion, and is passed the expansion.
3986
+ */
3987
+ Ember.expandProperties = function (pattern, callback) {
3988
+
3989
+ callback(pattern);
3990
+ };
3991
+
3992
+ })();
3993
+
3994
+
3995
+
3900
3996
  (function() {
3901
3997
  var metaFor = Ember.meta, // utils.js
3902
3998
  typeOf = Ember.typeOf, // utils.js
@@ -3951,6 +4047,7 @@ Ember.unwatchPath = function(obj, keyPath) {
3951
4047
  var metaFor = Ember.meta, // utils.js
3952
4048
  GUID_KEY = Ember.GUID_KEY, // utils.js
3953
4049
  META_KEY = Ember.META_KEY, // utils.js
4050
+ expandProperties = Ember.expandProperties,
3954
4051
  removeChainWatcher = Ember.removeChainWatcher,
3955
4052
  watchKey = Ember.watchKey, // watch_key.js
3956
4053
  unwatchKey = Ember.unwatchKey,
@@ -3979,15 +4076,17 @@ function isKeyName(path) {
3979
4076
  @param obj
3980
4077
  @param {String} keyName
3981
4078
  */
3982
- Ember.watch = function(obj, keyPath) {
4079
+ Ember.watch = function(obj, _keyPath) {
3983
4080
  // can't watch length on Array - it is special...
3984
- if (keyPath === 'length' && typeOf(obj) === 'array') { return; }
4081
+ if (_keyPath === 'length' && typeOf(obj) === 'array') { return; }
3985
4082
 
3986
- if (isKeyName(keyPath)) {
3987
- watchKey(obj, keyPath);
3988
- } else {
3989
- watchPath(obj, keyPath);
3990
- }
4083
+ expandProperties(_keyPath, function (keyPath) {
4084
+ if (isKeyName(keyPath)) {
4085
+ watchKey(obj, keyPath);
4086
+ } else {
4087
+ watchPath(obj, keyPath);
4088
+ }
4089
+ });
3991
4090
  };
3992
4091
 
3993
4092
  Ember.isWatching = function isWatching(obj, key) {
@@ -3997,15 +4096,17 @@ Ember.isWatching = function isWatching(obj, key) {
3997
4096
 
3998
4097
  Ember.watch.flushPending = Ember.flushPendingChains;
3999
4098
 
4000
- Ember.unwatch = function(obj, keyPath) {
4099
+ Ember.unwatch = function(obj, _keyPath) {
4001
4100
  // can't watch length on Array - it is special...
4002
- if (keyPath === 'length' && typeOf(obj) === 'array') { return; }
4101
+ if (_keyPath === 'length' && typeOf(obj) === 'array') { return; }
4003
4102
 
4004
- if (isKeyName(keyPath)) {
4005
- unwatchKey(obj, keyPath);
4006
- } else {
4007
- unwatchPath(obj, keyPath);
4008
- }
4103
+ expandProperties(_keyPath, function (keyPath) {
4104
+ if (isKeyName(keyPath)) {
4105
+ unwatchKey(obj, keyPath);
4106
+ } else {
4107
+ unwatchPath(obj, keyPath);
4108
+ }
4109
+ });
4009
4110
  };
4010
4111
 
4011
4112
  /**
@@ -4024,7 +4125,7 @@ Ember.rewatch = function(obj) {
4024
4125
 
4025
4126
  // make sure the object has its own guid.
4026
4127
  if (GUID_KEY in obj && !obj.hasOwnProperty(GUID_KEY)) {
4027
- generateGuid(obj, 'ember');
4128
+ generateGuid(obj);
4028
4129
  }
4029
4130
 
4030
4131
  // make sure any chained watchers update.
@@ -4091,6 +4192,7 @@ Ember.warn("The CP_DEFAULT_CACHEABLE flag has been removed and computed properti
4091
4192
  var get = Ember.get,
4092
4193
  set = Ember.set,
4093
4194
  metaFor = Ember.meta,
4195
+ expandProperties = Ember.expandProperties,
4094
4196
  a_slice = [].slice,
4095
4197
  o_create = Ember.create,
4096
4198
  META_KEY = Ember.META_KEY,
@@ -4350,9 +4452,13 @@ ComputedPropertyPrototype.readOnly = function(readOnly) {
4350
4452
  @chainable
4351
4453
  */
4352
4454
  ComputedPropertyPrototype.property = function() {
4455
+ function addArg(arg) {
4456
+ args.push(arg);
4457
+ }
4458
+
4353
4459
  var args = [];
4354
4460
  for (var i = 0, l = arguments.length; i < l; i++) {
4355
- args.push(arguments[i]);
4461
+ expandProperties(arguments[i], addArg);
4356
4462
  }
4357
4463
  this._dependentKeys = args;
4358
4464
  return this;
@@ -4481,7 +4587,7 @@ ComputedPropertyPrototype.set = function(obj, keyName, value) {
4481
4587
  funcArgLength, cachedValue, ret;
4482
4588
 
4483
4589
  if (this._readOnly) {
4484
- throw new Error('Cannot Set: ' + keyName + ' on: ' + obj.toString() );
4590
+ throw new Ember.Error('Cannot Set: ' + keyName + ' on: ' + obj.toString() );
4485
4591
  }
4486
4592
 
4487
4593
  this._suspended = obj;
@@ -4571,7 +4677,7 @@ Ember.computed = function(func) {
4571
4677
  }
4572
4678
 
4573
4679
  if (typeof func !== "function") {
4574
- throw new Error("Computed Property declared without a property function");
4680
+ throw new Ember.Error("Computed Property declared without a property function");
4575
4681
  }
4576
4682
 
4577
4683
  var cp = new ComputedProperty(func);
@@ -5205,8 +5311,9 @@ Ember.computed.defaultTo = function(defaultPath) {
5205
5311
  @module ember-metal
5206
5312
  */
5207
5313
 
5208
- var AFTER_OBSERVERS = ':change';
5209
- var BEFORE_OBSERVERS = ':before';
5314
+ var AFTER_OBSERVERS = ':change',
5315
+ BEFORE_OBSERVERS = ':before',
5316
+ expandProperties = Ember.expandProperties;
5210
5317
 
5211
5318
  function changeEvent(keyName) {
5212
5319
  return keyName+AFTER_OBSERVERS;
@@ -5223,9 +5330,12 @@ function beforeEvent(keyName) {
5223
5330
  @param {Object|Function} targetOrMethod
5224
5331
  @param {Function|String} [method]
5225
5332
  */
5226
- Ember.addObserver = function(obj, path, target, method) {
5227
- Ember.addListener(obj, changeEvent(path), target, method);
5228
- Ember.watch(obj, path);
5333
+ Ember.addObserver = function(obj, _path, target, method) {
5334
+ expandProperties(_path, function (path) {
5335
+ Ember.addListener(obj, changeEvent(path), target, method);
5336
+ Ember.watch(obj, path);
5337
+ });
5338
+
5229
5339
  return this;
5230
5340
  };
5231
5341
 
@@ -5240,9 +5350,11 @@ Ember.observersFor = function(obj, path) {
5240
5350
  @param {Object|Function} targetOrMethod
5241
5351
  @param {Function|String} [method]
5242
5352
  */
5243
- Ember.removeObserver = function(obj, path, target, method) {
5244
- Ember.unwatch(obj, path);
5245
- Ember.removeListener(obj, changeEvent(path), target, method);
5353
+ Ember.removeObserver = function(obj, _path, target, method) {
5354
+ expandProperties(_path, function (path) {
5355
+ Ember.unwatch(obj, path);
5356
+ Ember.removeListener(obj, changeEvent(path), target, method);
5357
+ });
5246
5358
  return this;
5247
5359
  };
5248
5360
 
@@ -5253,9 +5365,11 @@ Ember.removeObserver = function(obj, path, target, method) {
5253
5365
  @param {Object|Function} targetOrMethod
5254
5366
  @param {Function|String} [method]
5255
5367
  */
5256
- Ember.addBeforeObserver = function(obj, path, target, method) {
5257
- Ember.addListener(obj, beforeEvent(path), target, method);
5258
- Ember.watch(obj, path);
5368
+ Ember.addBeforeObserver = function(obj, _path, target, method) {
5369
+ expandProperties(_path, function (path) {
5370
+ Ember.addListener(obj, beforeEvent(path), target, method);
5371
+ Ember.watch(obj, path);
5372
+ });
5259
5373
  return this;
5260
5374
  };
5261
5375
 
@@ -5294,11 +5408,14 @@ Ember.beforeObserversFor = function(obj, path) {
5294
5408
  @param {Object|Function} targetOrMethod
5295
5409
  @param {Function|String} [method]
5296
5410
  */
5297
- Ember.removeBeforeObserver = function(obj, path, target, method) {
5298
- Ember.unwatch(obj, path);
5299
- Ember.removeListener(obj, beforeEvent(path), target, method);
5411
+ Ember.removeBeforeObserver = function(obj, _path, target, method) {
5412
+ expandProperties(_path, function (path) {
5413
+ Ember.unwatch(obj, path);
5414
+ Ember.removeListener(obj, beforeEvent(path), target, method);
5415
+ });
5300
5416
  return this;
5301
5417
  };
5418
+
5302
5419
  })();
5303
5420
 
5304
5421
 
@@ -5733,7 +5850,7 @@ define("backburner",
5733
5850
  throttle: function(target, method /* , args, wait */) {
5734
5851
  var self = this,
5735
5852
  args = arguments,
5736
- wait = pop.call(args),
5853
+ wait = parseInt(pop.call(args), 10),
5737
5854
  throttler;
5738
5855
 
5739
5856
  for (var i = 0, l = throttlers.length; i < l; i++) {
@@ -5768,13 +5885,14 @@ define("backburner",
5768
5885
  index,
5769
5886
  debouncee;
5770
5887
 
5771
- if (typeof immediate === "number") {
5888
+ if (typeof immediate === "number" || typeof immediate === "string") {
5772
5889
  wait = immediate;
5773
5890
  immediate = false;
5774
5891
  } else {
5775
5892
  wait = pop.call(args);
5776
5893
  }
5777
5894
 
5895
+ wait = parseInt(wait, 10);
5778
5896
  // Remove debouncee
5779
5897
  index = findDebouncee(target, method);
5780
5898
 
@@ -7040,7 +7158,9 @@ function applyConcatenatedProperties(obj, key, value, values) {
7040
7158
  return Ember.makeArray(baseValue).concat(value);
7041
7159
  }
7042
7160
  } else {
7043
- return Ember.makeArray(value);
7161
+ // Make sure this mixin has its own array so it is not
7162
+ // accidentally mutated by another child's interactions
7163
+ return Ember.makeArray(value).slice();
7044
7164
  }
7045
7165
  }
7046
7166
 
@@ -7557,9 +7677,9 @@ Ember.aliasMethod = function(methodName) {
7557
7677
 
7558
7678
  ```javascript
7559
7679
  Ember.Object.extend({
7560
- valueObserver: Ember.observer(function() {
7680
+ valueObserver: Ember.observer('value', function() {
7561
7681
  // Executes whenever the "value" property changes
7562
- }, 'value')
7682
+ })
7563
7683
  });
7564
7684
  ```
7565
7685
 
@@ -7571,12 +7691,25 @@ Ember.aliasMethod = function(methodName) {
7571
7691
 
7572
7692
  @method observer
7573
7693
  @for Ember
7574
- @param {Function} func
7575
7694
  @param {String} propertyNames*
7695
+ @param {Function} func
7576
7696
  @return func
7577
7697
  */
7578
- Ember.observer = function(func) {
7579
- var paths = a_slice.call(arguments, 1);
7698
+ Ember.observer = function() {
7699
+ var func = a_slice.call(arguments, -1)[0];
7700
+ var paths = a_slice.call(arguments, 0, -1);
7701
+
7702
+ if (typeof func !== "function") {
7703
+ // revert to old, soft-deprecated argument ordering
7704
+
7705
+ func = arguments[0];
7706
+ paths = a_slice.call(arguments, 1);
7707
+ }
7708
+
7709
+ if (typeof func !== "function") {
7710
+ throw new Ember.Error("Ember.observer called without a function");
7711
+ }
7712
+
7580
7713
  func.__ember_observes__ = paths;
7581
7714
  return func;
7582
7715
  };
@@ -7586,9 +7719,9 @@ Ember.observer = function(func) {
7586
7719
 
7587
7720
  ```javascript
7588
7721
  Ember.Object.extend({
7589
- valueObserver: Ember.immediateObserver(function() {
7722
+ valueObserver: Ember.immediateObserver('value', function() {
7590
7723
  // Executes whenever the "value" property changes
7591
- }, 'value')
7724
+ })
7592
7725
  });
7593
7726
  ```
7594
7727
 
@@ -7600,8 +7733,8 @@ Ember.observer = function(func) {
7600
7733
 
7601
7734
  @method immediateObserver
7602
7735
  @for Ember
7603
- @param {Function} func
7604
7736
  @param {String} propertyNames*
7737
+ @param {Function} func
7605
7738
  @return func
7606
7739
  */
7607
7740
  Ember.immediateObserver = function() {
@@ -7628,22 +7761,22 @@ Ember.immediateObserver = function() {
7628
7761
 
7629
7762
  friends: [{ name: 'Tom' }, { name: 'Stefan' }, { name: 'Kris' }],
7630
7763
 
7631
- valueWillChange: Ember.beforeObserver(function(obj, keyName) {
7764
+ valueWillChange: Ember.beforeObserver('content.value', function(obj, keyName) {
7632
7765
  this.changingFrom = obj.get(keyName);
7633
- }, 'content.value'),
7766
+ }),
7634
7767
 
7635
- valueDidChange: Ember.observer(function(obj, keyName) {
7768
+ valueDidChange: Ember.observer('content.value', function(obj, keyName) {
7636
7769
  // only run if updating a value already in the DOM
7637
7770
  if (this.get('state') === 'inDOM') {
7638
7771
  var color = obj.get(keyName) > this.changingFrom ? 'green' : 'red';
7639
7772
  // logic
7640
7773
  }
7641
- }, 'content.value'),
7774
+ }),
7642
7775
 
7643
- friendsDidChange: Ember.observer(function(obj, keyName) {
7776
+ friendsDidChange: Ember.observer('friends.@each.name', function(obj, keyName) {
7644
7777
  // some logic
7645
7778
  // obj.get(keyName) returns friends array
7646
- }, 'friends.@each.name')
7779
+ })
7647
7780
  });
7648
7781
  ```
7649
7782
 
@@ -7652,12 +7785,25 @@ Ember.immediateObserver = function() {
7652
7785
 
7653
7786
  @method beforeObserver
7654
7787
  @for Ember
7655
- @param {Function} func
7656
7788
  @param {String} propertyNames*
7789
+ @param {Function} func
7657
7790
  @return func
7658
7791
  */
7659
- Ember.beforeObserver = function(func) {
7660
- var paths = a_slice.call(arguments, 1);
7792
+ Ember.beforeObserver = function() {
7793
+ var func = a_slice.call(arguments, -1)[0];
7794
+ var paths = a_slice.call(arguments, 0, -1);
7795
+
7796
+ if (typeof func !== "function") {
7797
+ // revert to old, soft-deprecated argument ordering
7798
+
7799
+ func = arguments[0];
7800
+ paths = a_slice.call(arguments, 1);
7801
+ }
7802
+
7803
+ if (typeof func !== "function") {
7804
+ throw new Ember.Error("Ember.beforeObserver called without a function");
7805
+ }
7806
+
7661
7807
  func.__ember_observesBefore__ = paths;
7662
7808
  return func;
7663
7809
  };
@@ -9572,31 +9718,6 @@ if (!Ember.keys || Ember.create.isSimulated) {
9572
9718
  };
9573
9719
  }
9574
9720
 
9575
- // ..........................................................
9576
- // ERROR
9577
- //
9578
-
9579
- var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack'];
9580
-
9581
- /**
9582
- A subclass of the JavaScript Error object for use in Ember.
9583
-
9584
- @class Error
9585
- @namespace Ember
9586
- @extends Error
9587
- @constructor
9588
- */
9589
- Ember.Error = function() {
9590
- var tmp = Error.apply(this, arguments);
9591
-
9592
- // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work.
9593
- for (var idx = 0; idx < errorProps.length; idx++) {
9594
- this[errorProps[idx]] = tmp[errorProps[idx]];
9595
- }
9596
- };
9597
-
9598
- Ember.Error.prototype = Ember.create(Error.prototype);
9599
-
9600
9721
  })();
9601
9722
 
9602
9723
 
@@ -10567,7 +10688,36 @@ Ember.Enumerable = Ember.Mixin.create({
10567
10688
  return this ;
10568
10689
  }
10569
10690
 
10570
- }) ;
10691
+ });
10692
+
10693
+
10694
+ Ember.Enumerable.reopen({
10695
+ /**
10696
+ Converts the enumerable into an array and sorts by the keys
10697
+ specified in the argument.
10698
+
10699
+ You may provide multiple arguments to sort by multiple properties.
10700
+
10701
+ @method sortBy
10702
+ @param {String} property name(s) to sort on
10703
+ @return {Array} The sorted array.
10704
+ */
10705
+ sortBy: function() {
10706
+ var sortKeys = arguments;
10707
+ return this.toArray().sort(function(a, b){
10708
+ for(var i = 0; i < sortKeys.length; i++) {
10709
+ var key = sortKeys[i],
10710
+ propA = get(a, key),
10711
+ propB = get(b, key);
10712
+ // return 1 or -1 else continue to the next sortKey
10713
+ var compareValue = Ember.compare(propA, propB);
10714
+ if (compareValue) { return compareValue; }
10715
+ }
10716
+ return 0;
10717
+ });
10718
+ }
10719
+ });
10720
+
10571
10721
 
10572
10722
  })();
10573
10723
 
@@ -11003,7 +11153,7 @@ Ember.Array = Ember.Mixin.create(Ember.Enumerable, /** @scope Ember.Array.protot
11003
11153
 
11004
11154
 
11005
11155
  (function() {
11006
- var get = Ember.get,
11156
+ var e_get = Ember.get,
11007
11157
  set = Ember.set,
11008
11158
  guidFor = Ember.guidFor,
11009
11159
  metaFor = Ember.meta,
@@ -11022,6 +11172,16 @@ var get = Ember.get,
11022
11172
  eachPropertyPattern = /^(.*)\.@each\.(.*)/,
11023
11173
  doubleEachPropertyPattern = /(.*\.@each){2,}/;
11024
11174
 
11175
+ function get(obj, key) {
11176
+
11177
+ if (key === '@this') {
11178
+ return obj;
11179
+ }
11180
+
11181
+
11182
+ return e_get(obj, key);
11183
+ }
11184
+
11025
11185
  /*
11026
11186
  Tracks changes to dependent arrays, as well as to properties of items in
11027
11187
  dependent arrays.
@@ -11213,12 +11373,14 @@ DependentArraysObserver.prototype = {
11213
11373
  guid = guidFor(dependentArray),
11214
11374
  dependentKey = this.dependentKeysByGuid[guid],
11215
11375
  itemPropertyKeys = this.cp._itemPropertyKeys[dependentKey] || [],
11376
+ length = get(dependentArray, 'length'),
11377
+ normalizedIndex = normalizeIndex(length, index, 1),
11216
11378
  item,
11217
11379
  itemIndex,
11218
11380
  sliceIndex,
11219
11381
  observerContexts;
11220
11382
 
11221
- observerContexts = this.trackRemove(dependentKey, index, removedCount);
11383
+ observerContexts = this.trackRemove(dependentKey, normalizedIndex, removedCount);
11222
11384
 
11223
11385
  function removeObservers(propertyKey) {
11224
11386
  observerContexts[sliceIndex].destroyed = true;
@@ -11227,7 +11389,9 @@ DependentArraysObserver.prototype = {
11227
11389
  }
11228
11390
 
11229
11391
  for (sliceIndex = removedCount - 1; sliceIndex >= 0; --sliceIndex) {
11230
- itemIndex = index + sliceIndex;
11392
+ itemIndex = normalizedIndex + sliceIndex;
11393
+ if (itemIndex >= length) { break; }
11394
+
11231
11395
  item = dependentArray.objectAt(itemIndex);
11232
11396
 
11233
11397
  forEach(itemPropertyKeys, removeObservers, this);
@@ -11244,26 +11408,28 @@ DependentArraysObserver.prototype = {
11244
11408
  dependentKey = this.dependentKeysByGuid[guid],
11245
11409
  observerContexts = new Array(addedCount),
11246
11410
  itemPropertyKeys = this.cp._itemPropertyKeys[dependentKey],
11411
+ length = get(dependentArray, 'length'),
11412
+ normalizedIndex = normalizeIndex(length, index, addedCount),
11247
11413
  changeMeta,
11248
11414
  observerContext;
11249
11415
 
11250
- forEach(dependentArray.slice(index, index + addedCount), function (item, sliceIndex) {
11416
+ forEach(dependentArray.slice(normalizedIndex, normalizedIndex + addedCount), function (item, sliceIndex) {
11251
11417
  if (itemPropertyKeys) {
11252
11418
  observerContext =
11253
11419
  observerContexts[sliceIndex] =
11254
- this.createPropertyObserverContext(dependentArray, index + sliceIndex, this.trackedArraysByGuid[dependentKey]);
11420
+ this.createPropertyObserverContext(dependentArray, normalizedIndex + sliceIndex, this.trackedArraysByGuid[dependentKey]);
11255
11421
  forEach(itemPropertyKeys, function (propertyKey) {
11256
11422
  addBeforeObserver(item, propertyKey, this, observerContext.beforeObserver);
11257
11423
  addObserver(item, propertyKey, this, observerContext.observer);
11258
11424
  }, this);
11259
11425
  }
11260
11426
 
11261
- changeMeta = createChangeMeta(dependentArray, item, index + sliceIndex, this.instanceMeta.propertyName, this.cp);
11427
+ changeMeta = createChangeMeta(dependentArray, item, normalizedIndex + sliceIndex, this.instanceMeta.propertyName, this.cp);
11262
11428
  this.setValue( addedItem.call(
11263
11429
  this.instanceMeta.context, this.getValue(), item, changeMeta, this.instanceMeta.sugarMeta));
11264
11430
  }, this);
11265
11431
 
11266
- this.trackAdd(dependentKey, index, observerContexts);
11432
+ this.trackAdd(dependentKey, normalizedIndex, observerContexts);
11267
11433
  },
11268
11434
 
11269
11435
  itemPropertyWillChange: function (obj, keyName, array, observerContext) {
@@ -11304,6 +11470,16 @@ DependentArraysObserver.prototype = {
11304
11470
  }
11305
11471
  };
11306
11472
 
11473
+ function normalizeIndex(length, index, newItemsOffset) {
11474
+ if (index < 0) {
11475
+ return Math.max(0, length + index);
11476
+ } else if (index < length) {
11477
+ return index;
11478
+ } else /* index > length */ {
11479
+ return Math.min(length - newItemsOffset, index);
11480
+ }
11481
+ }
11482
+
11307
11483
  function createChangeMeta(dependentArray, item, index, propertyName, property, previousValues) {
11308
11484
  var meta = {
11309
11485
  arrayChanged: dependentArray,
@@ -11668,6 +11844,37 @@ ReduceComputedProperty.prototype.property = function () {
11668
11844
  };
11669
11845
  ```
11670
11846
 
11847
+ Dependent keys may refer to `@this` to observe changes to the object itself,
11848
+ which must be array-like, rather than a property of the object. This is
11849
+ mostly useful for array proxies, to ensure objects are retrieved via
11850
+ `objectAtContent`. This is how you could sort items by properties defined on an item controller.
11851
+
11852
+ Example
11853
+
11854
+ ```javascript
11855
+ App.PeopleController = Ember.ArrayController.extend({
11856
+ itemController: 'person',
11857
+
11858
+ sortedPeople: Ember.computed.sort('@this.@each.reversedName', function(personA, personB) {
11859
+ // `reversedName` isn't defined on Person, but we have access to it via
11860
+ // the item controller App.PersonController. If we'd used
11861
+ // `content.@each.reversedName` above, we would be getting the objects
11862
+ // directly and not have access to `reversedName`.
11863
+ //
11864
+ var reversedNameA = get(personA, 'reversedName'),
11865
+ reversedNameB = get(personB, 'reversedName');
11866
+
11867
+ return Ember.compare(reversedNameA, reversedNameB);
11868
+ })
11869
+ });
11870
+
11871
+ App.PersonController = Ember.ObjectController.extend({
11872
+ reversedName: function () {
11873
+ return reverse(get(this, 'name'));
11874
+ }.property('name')
11875
+ })
11876
+ ```
11877
+
11671
11878
  @method reduceComputed
11672
11879
  @for Ember
11673
11880
  @param {String} [dependentKeys*]
@@ -12850,9 +13057,10 @@ Ember.String = {
12850
13057
  capitalize: function(str) {
12851
13058
  return str.charAt(0).toUpperCase() + str.substr(1);
12852
13059
  }
12853
-
12854
13060
  };
12855
13061
 
13062
+
13063
+
12856
13064
  })();
12857
13065
 
12858
13066
 
@@ -12875,6 +13083,7 @@ var fmt = Ember.String.fmt,
12875
13083
  capitalize = Ember.String.capitalize,
12876
13084
  classify = Ember.String.classify;
12877
13085
 
13086
+
12878
13087
  if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.String) {
12879
13088
 
12880
13089
  /**
@@ -12967,6 +13176,7 @@ if (Ember.EXTEND_PROTOTYPES === true || Ember.EXTEND_PROTOTYPES.String) {
12967
13176
  return capitalize(this);
12968
13177
  };
12969
13178
 
13179
+
12970
13180
  }
12971
13181
 
12972
13182
 
@@ -13904,7 +14114,7 @@ Ember.Observable = Ember.Mixin.create({
13904
14114
 
13905
14115
  ```javascript
13906
14116
  fullName: function() {
13907
- return this.getEach('firstName', 'lastName').compact().join(' ');
14117
+ return this.get('firstName') + ' ' + this.get('lastName');
13908
14118
  }.property('firstName', 'lastName')
13909
14119
  ```
13910
14120
 
@@ -14201,29 +14411,6 @@ Ember.Observable = Ember.Mixin.create({
14201
14411
  return Ember.hasListeners(this, key+':change');
14202
14412
  },
14203
14413
 
14204
- /**
14205
- @deprecated
14206
- @method getPath
14207
- @param {String} path The property path to retrieve
14208
- @return {Object} The property value or undefined.
14209
- */
14210
- getPath: function(path) {
14211
- Ember.deprecate("getPath is deprecated since get now supports paths");
14212
- return this.get(path);
14213
- },
14214
-
14215
- /**
14216
- @deprecated
14217
- @method setPath
14218
- @param {String} path The path to the property that will be set
14219
- @param {Object} value The value to set or `null`.
14220
- @return {Ember.Observable}
14221
- */
14222
- setPath: function(path, value) {
14223
- Ember.deprecate("setPath is deprecated since set now supports paths");
14224
- return this.set(path, value);
14225
- },
14226
-
14227
14414
  /**
14228
14415
  Retrieves the value of a property, or a default value in the case that the
14229
14416
  property returns `undefined`.
@@ -14701,7 +14888,7 @@ Ember.DeferredMixin = Ember.Mixin.create({
14701
14888
  @submodule ember-runtime
14702
14889
  */
14703
14890
 
14704
- var get = Ember.get;
14891
+ var get = Ember.get, typeOf = Ember.typeOf;
14705
14892
 
14706
14893
  /**
14707
14894
  The `Ember.ActionHandler` mixin implements support for moving an `actions`
@@ -14727,9 +14914,21 @@ Ember.ActionHandler = Ember.Mixin.create({
14727
14914
  @method willMergeMixin
14728
14915
  */
14729
14916
  willMergeMixin: function(props) {
14730
- if (props.actions && !props._actions) {
14731
- props._actions = Ember.merge(props._actions || {}, props.actions);
14732
- delete props.actions;
14917
+ var hashName;
14918
+
14919
+ if (!props._actions) {
14920
+ if (typeOf(props.actions) === 'object') {
14921
+ hashName = 'actions';
14922
+ } else if (typeOf(props.events) === 'object') {
14923
+ Ember.deprecate('Action handlers contained in an `events` object are deprecated in favor of putting them in an `actions` object', false);
14924
+ hashName = 'events';
14925
+ }
14926
+
14927
+ if (hashName) {
14928
+ props._actions = Ember.merge(props._actions || {}, props[hashName]);
14929
+ }
14930
+
14931
+ delete props[hashName];
14733
14932
  }
14734
14933
  },
14735
14934
 
@@ -15387,6 +15586,14 @@ Ember.SubArray.prototype = {
15387
15586
  this._operations.splice(index+1, 1);
15388
15587
  }
15389
15588
  }
15589
+ },
15590
+
15591
+ toString: function () {
15592
+ var str = "";
15593
+ forEach(this._operations, function (operation) {
15594
+ str += " " + operation.type + ":" + operation.count;
15595
+ });
15596
+ return str.substring(1);
15390
15597
  }
15391
15598
  };
15392
15599
 
@@ -15473,10 +15680,7 @@ function makeCtor() {
15473
15680
 
15474
15681
  Ember.assert("Ember.Object.create no longer supports mixing in other definitions, use createWithMixins instead.", !(properties instanceof Ember.Mixin));
15475
15682
 
15476
- if (properties === null || typeof properties !== 'object') {
15477
- Ember.assert("Ember.Object.create only accepts objects.");
15478
- continue;
15479
- }
15683
+ if (Ember.typeOf(properties) !== 'object') { continue; }
15480
15684
 
15481
15685
  var keyNames = Ember.keys(properties);
15482
15686
  for (var j = 0, ll = keyNames.length; j < ll; j++) {
@@ -15668,7 +15872,7 @@ CoreObject.PrototypeMixin = Mixin.create({
15668
15872
  This feature is available for you to use throughout the Ember object model,
15669
15873
  although typical app developers are likely to use it infrequently. Since
15670
15874
  it changes expectations about behavior of properties, you should properly
15671
- document its usage in each individual concatenated property (to not
15875
+ document its usage in each individual concatenated property (to not
15672
15876
  mislead your users to think they can override the property in a subclass).
15673
15877
 
15674
15878
  @property concatenatedProperties
@@ -15904,7 +16108,7 @@ var ClassMixin = Mixin.create({
15904
16108
 
15905
16109
  proto = Class.prototype = o_create(this.prototype);
15906
16110
  proto.constructor = Class;
15907
- generateGuid(proto, 'ember');
16111
+ generateGuid(proto);
15908
16112
  meta(proto).proto = proto; // this will disable observers on prototype
15909
16113
 
15910
16114
  Class.ClassMixin.apply(Class);
@@ -15969,10 +16173,10 @@ var ClassMixin = Mixin.create({
15969
16173
  },
15970
16174
 
15971
16175
  /**
15972
-
16176
+
15973
16177
  Augments a constructor's prototype with additional
15974
16178
  properties and functions:
15975
-
16179
+
15976
16180
  ```javascript
15977
16181
  MyObject = Ember.Object.extend({
15978
16182
  name: 'an object'
@@ -15992,7 +16196,7 @@ var ClassMixin = Mixin.create({
15992
16196
 
15993
16197
  o.say("goodbye"); // logs "goodbye"
15994
16198
  ```
15995
-
16199
+
15996
16200
  To add functions and properties to the constructor itself,
15997
16201
  see `reopenClass`
15998
16202
 
@@ -16006,7 +16210,7 @@ var ClassMixin = Mixin.create({
16006
16210
 
16007
16211
  /**
16008
16212
  Augments a constructor's own properties and functions:
16009
-
16213
+
16010
16214
  ```javascript
16011
16215
  MyObject = Ember.Object.extend({
16012
16216
  name: 'an object'
@@ -16016,12 +16220,12 @@ var ClassMixin = Mixin.create({
16016
16220
  MyObject.reopenClass({
16017
16221
  canBuild: false
16018
16222
  });
16019
-
16223
+
16020
16224
  MyObject.canBuild; // false
16021
16225
  o = MyObject.create();
16022
16226
  ```
16023
16227
 
16024
- In other words, this creates static properties and functions for the class. These are only available on the class
16228
+ In other words, this creates static properties and functions for the class. These are only available on the class
16025
16229
  and not on any instance of that class.
16026
16230
 
16027
16231
  ```javascript
@@ -16051,15 +16255,15 @@ var ClassMixin = Mixin.create({
16051
16255
  alert(App.Person.species); // "Homo sapiens"
16052
16256
  ```
16053
16257
 
16054
- Note that `species` and `createPerson` are *not* valid on the `tom` and `yehuda`
16258
+ Note that `species` and `createPerson` are *not* valid on the `tom` and `yehuda`
16055
16259
  variables. They are only valid on `App.Person`.
16056
-
16260
+
16057
16261
  To add functions and properties to instances of
16058
16262
  a constructor by extending the constructor's prototype
16059
16263
  see `reopen`
16060
-
16264
+
16061
16265
  @method reopenClass
16062
- */
16266
+ */
16063
16267
  reopenClass: function() {
16064
16268
  reopen.apply(this.ClassMixin, arguments);
16065
16269
  applyMixin(this, arguments, false);
@@ -16500,9 +16704,9 @@ Ember.ArrayProxy = Ember.Object.extend(Ember.MutableArray,/** @scope Ember.Array
16500
16704
 
16501
16705
  @method _contentWillChange
16502
16706
  */
16503
- _contentWillChange: Ember.beforeObserver(function() {
16707
+ _contentWillChange: Ember.beforeObserver('content', function() {
16504
16708
  this._teardownContent();
16505
- }, 'content'),
16709
+ }),
16506
16710
 
16507
16711
  _teardownContent: function() {
16508
16712
  var content = get(this, 'content');
@@ -16526,13 +16730,13 @@ Ember.ArrayProxy = Ember.Object.extend(Ember.MutableArray,/** @scope Ember.Array
16526
16730
 
16527
16731
  @method _contentDidChange
16528
16732
  */
16529
- _contentDidChange: Ember.observer(function() {
16733
+ _contentDidChange: Ember.observer('content', function() {
16530
16734
  var content = get(this, 'content');
16531
16735
 
16532
16736
  Ember.assert("Can't set ArrayProxy's content to itself", content !== this);
16533
16737
 
16534
16738
  this._setupContent();
16535
- }, 'content'),
16739
+ }),
16536
16740
 
16537
16741
  _setupContent: function() {
16538
16742
  var content = get(this, 'content');
@@ -16545,7 +16749,7 @@ Ember.ArrayProxy = Ember.Object.extend(Ember.MutableArray,/** @scope Ember.Array
16545
16749
  }
16546
16750
  },
16547
16751
 
16548
- _arrangedContentWillChange: Ember.beforeObserver(function() {
16752
+ _arrangedContentWillChange: Ember.beforeObserver('arrangedContent', function() {
16549
16753
  var arrangedContent = get(this, 'arrangedContent'),
16550
16754
  len = arrangedContent ? get(arrangedContent, 'length') : 0;
16551
16755
 
@@ -16553,9 +16757,9 @@ Ember.ArrayProxy = Ember.Object.extend(Ember.MutableArray,/** @scope Ember.Array
16553
16757
  this.arrangedContentWillChange(this);
16554
16758
 
16555
16759
  this._teardownArrangedContent(arrangedContent);
16556
- }, 'arrangedContent'),
16760
+ }),
16557
16761
 
16558
- _arrangedContentDidChange: Ember.observer(function() {
16762
+ _arrangedContentDidChange: Ember.observer('arrangedContent', function() {
16559
16763
  var arrangedContent = get(this, 'arrangedContent'),
16560
16764
  len = arrangedContent ? get(arrangedContent, 'length') : 0;
16561
16765
 
@@ -16565,7 +16769,7 @@ Ember.ArrayProxy = Ember.Object.extend(Ember.MutableArray,/** @scope Ember.Array
16565
16769
 
16566
16770
  this.arrangedContentDidChange(this);
16567
16771
  this.arrangedContentArrayDidChange(this, 0, undefined, len);
16568
- }, 'arrangedContent'),
16772
+ }),
16569
16773
 
16570
16774
  _setupArrangedContent: function() {
16571
16775
  var arrangedContent = get(this, 'arrangedContent');
@@ -16828,9 +17032,9 @@ Ember.ObjectProxy = Ember.Object.extend(/** @scope Ember.ObjectProxy.prototype *
16828
17032
  @default null
16829
17033
  */
16830
17034
  content: null,
16831
- _contentDidChange: Ember.observer(function() {
17035
+ _contentDidChange: Ember.observer('content', function() {
16832
17036
  Ember.assert("Can't set ObjectProxy's content to itself", this.get('content') !== this);
16833
- }, 'content'),
17037
+ }),
16834
17038
 
16835
17039
  isTruthy: Ember.computed.bool('content'),
16836
17040
 
@@ -17121,7 +17325,7 @@ var NativeArray = Ember.Mixin.create(Ember.MutableArray, Ember.Observable, Ember
17121
17325
  var len = objects ? get(objects, 'length') : 0;
17122
17326
  this.arrayContentWillChange(idx, amt, len);
17123
17327
 
17124
- if (!objects || objects.length === 0) {
17328
+ if (len === 0) {
17125
17329
  this.splice(idx, amt);
17126
17330
  } else {
17127
17331
  replace(this, idx, amt, objects);
@@ -18052,7 +18256,7 @@ Ember.SortableMixin = Ember.Mixin.create(Ember.MutableEnumerable, {
18052
18256
  return content;
18053
18257
  }),
18054
18258
 
18055
- _contentWillChange: Ember.beforeObserver(function() {
18259
+ _contentWillChange: Ember.beforeObserver('content', function() {
18056
18260
  var content = get(this, 'content'),
18057
18261
  sortProperties = get(this, 'sortProperties');
18058
18262
 
@@ -18065,18 +18269,18 @@ Ember.SortableMixin = Ember.Mixin.create(Ember.MutableEnumerable, {
18065
18269
  }
18066
18270
 
18067
18271
  this._super();
18068
- }, 'content'),
18272
+ }),
18069
18273
 
18070
- sortAscendingWillChange: Ember.beforeObserver(function() {
18274
+ sortAscendingWillChange: Ember.beforeObserver('sortAscending', function() {
18071
18275
  this._lastSortAscending = get(this, 'sortAscending');
18072
- }, 'sortAscending'),
18276
+ }),
18073
18277
 
18074
- sortAscendingDidChange: Ember.observer(function() {
18278
+ sortAscendingDidChange: Ember.observer('sortAscending', function() {
18075
18279
  if (get(this, 'sortAscending') !== this._lastSortAscending) {
18076
18280
  var arrangedContent = get(this, 'arrangedContent');
18077
18281
  arrangedContent.reverseObjects();
18078
18282
  }
18079
- }, 'sortAscending'),
18283
+ }),
18080
18284
 
18081
18285
  contentArrayWillChange: function(array, idx, removedCount, addedCount) {
18082
18286
  var isSorted = get(this, 'isSorted');