ember-source 1.5.0.beta.4 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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.5.0-beta.4
10
+ * @version 1.5.0
11
11
  */
12
12
 
13
13
 
@@ -177,6 +177,27 @@ Ember.deprecateFunc = function(message, func) {
177
177
  };
178
178
 
179
179
 
180
+ /**
181
+ Run a function meant for debugging. Ember build tools will remove any calls to
182
+ `Ember.runInDebug()` when doing a production build.
183
+
184
+ ```javascript
185
+ Ember.runInDebug( function() {
186
+ Ember.Handlebars.EachView.reopen({
187
+ didInsertElement: function() {
188
+ console.log("I'm happy");
189
+ }
190
+ });
191
+ });
192
+ ```
193
+
194
+ @method runInDebug
195
+ @param {Function} func The function to be executed.
196
+ */
197
+ Ember.runInDebug = function(func) {
198
+ func()
199
+ };
200
+
180
201
  // Inform the developer about the Ember Inspector if not installed.
181
202
  if (!Ember.testing) {
182
203
  var isFirefox = typeof InstallTrigger !== 'undefined';
@@ -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.5.0-beta.4
8
+ * @version 1.5.0
9
9
  */
10
10
 
11
11
 
@@ -175,6 +175,27 @@ Ember.deprecateFunc = function(message, func) {
175
175
  };
176
176
 
177
177
 
178
+ /**
179
+ Run a function meant for debugging. Ember build tools will remove any calls to
180
+ `Ember.runInDebug()` when doing a production build.
181
+
182
+ ```javascript
183
+ Ember.runInDebug( function() {
184
+ Ember.Handlebars.EachView.reopen({
185
+ didInsertElement: function() {
186
+ console.log("I'm happy");
187
+ }
188
+ });
189
+ });
190
+ ```
191
+
192
+ @method runInDebug
193
+ @param {Function} func The function to be executed.
194
+ */
195
+ Ember.runInDebug = function(func) {
196
+ func()
197
+ };
198
+
178
199
  // Inform the developer about the Ember Inspector if not installed.
179
200
  if (!Ember.testing) {
180
201
  var isFirefox = typeof InstallTrigger !== 'undefined';
@@ -206,7 +227,7 @@ if (!Ember.testing) {
206
227
  * Portions Copyright 2008-2011 Apple Inc. All rights reserved.
207
228
  * @license Licensed under MIT license
208
229
  * See https://raw.github.com/emberjs/ember.js/master/LICENSE
209
- * @version 1.5.0-beta.4
230
+ * @version 1.5.0
210
231
  */
211
232
 
212
233
 
@@ -289,7 +310,7 @@ var define, requireModule, require, requirejs;
289
310
 
290
311
  @class Ember
291
312
  @static
292
- @version 1.5.0-beta.4
313
+ @version 1.5.0
293
314
  */
294
315
 
295
316
  if ('undefined' === typeof Ember) {
@@ -316,10 +337,10 @@ Ember.toString = function() { return "Ember"; };
316
337
  /**
317
338
  @property VERSION
318
339
  @type String
319
- @default '1.5.0-beta.4'
340
+ @default '1.5.0'
320
341
  @static
321
342
  */
322
- Ember.VERSION = '1.5.0-beta.4';
343
+ Ember.VERSION = '1.5.0';
323
344
 
324
345
  /**
325
346
  Standard environmental variables. You can define these in a global `EmberENV`
@@ -462,6 +483,7 @@ Ember.K = function() { return this; };
462
483
  if ('undefined' === typeof Ember.assert) { Ember.assert = Ember.K; }
463
484
  if ('undefined' === typeof Ember.warn) { Ember.warn = Ember.K; }
464
485
  if ('undefined' === typeof Ember.debug) { Ember.debug = Ember.K; }
486
+ if ('undefined' === typeof Ember.runInDebug) { Ember.runInDebug = Ember.K; }
465
487
  if ('undefined' === typeof Ember.deprecate) { Ember.deprecate = Ember.K; }
466
488
  if ('undefined' === typeof Ember.deprecateFunc) {
467
489
  Ember.deprecateFunc = function(_, func) { return func; };
@@ -1093,6 +1115,7 @@ function Meta(obj) {
1093
1115
  this.descs = {};
1094
1116
  this.watching = {};
1095
1117
  this.cache = {};
1118
+ this.cacheMeta = {};
1096
1119
  this.source = obj;
1097
1120
  }
1098
1121
 
@@ -1102,6 +1125,7 @@ Meta.prototype = {
1102
1125
  watching: null,
1103
1126
  listeners: null,
1104
1127
  cache: null,
1128
+ cacheMeta: null,
1105
1129
  source: null,
1106
1130
  mixins: null,
1107
1131
  bindings: null,
@@ -1169,10 +1193,11 @@ Ember.meta = function meta(obj, writable) {
1169
1193
  if (!isDefinePropertySimulated) o_defineProperty(obj, META_KEY, META_DESC);
1170
1194
 
1171
1195
  ret = o_create(ret);
1172
- ret.descs = o_create(ret.descs);
1173
- ret.watching = o_create(ret.watching);
1174
- ret.cache = {};
1175
- ret.source = obj;
1196
+ ret.descs = o_create(ret.descs);
1197
+ ret.watching = o_create(ret.watching);
1198
+ ret.cache = {};
1199
+ ret.cacheMeta = {};
1200
+ ret.source = obj;
1176
1201
 
1177
1202
  if (MANDATORY_SETTER) { ret.values = o_create(ret.values); }
1178
1203
 
@@ -2029,12 +2054,12 @@ var utils = Ember.EnumerableUtils = {
2029
2054
  * @param {Array} array The array the objects should be inserted into.
2030
2055
  * @param {Number} idx Starting index in the array to replace. If *idx* >=
2031
2056
  * length, then append to the end of the array.
2032
- * @param {Number} amt Number of elements that should be remove from the array,
2057
+ * @param {Number} amt Number of elements that should be removed from the array,
2033
2058
  * starting at *idx*
2034
2059
  * @param {Array} objects An array of zero or more objects that should be
2035
2060
  * inserted into the array at *idx*
2036
2061
  *
2037
- * @return {Array} The changed array.
2062
+ * @return {Array} The modified array.
2038
2063
  */
2039
2064
  replace: function(array, idx, amt, objects) {
2040
2065
  if (array.replace) {
@@ -6735,9 +6760,9 @@ Ember.run.join = function(target, method /* args */) {
6735
6760
  when called within an existing loop, no return value is possible.
6736
6761
  */
6737
6762
  Ember.run.bind = function(target, method /* args*/) {
6738
- var args = arguments;
6763
+ var args = slice.call(arguments);
6739
6764
  return function() {
6740
- return Ember.run.join.apply(Ember.run, args);
6765
+ return Ember.run.join.apply(Ember.run, args.concat(slice.call(arguments)));
6741
6766
  };
6742
6767
  };
6743
6768
 
@@ -7069,8 +7094,6 @@ Ember.run.next = function() {
7069
7094
  // the 100ms delay until this method can be called again will be cancelled
7070
7095
  Ember.run.cancel(debounceImmediate);
7071
7096
  ```
7072
- ```
7073
- ```
7074
7097
 
7075
7098
  @method cancel
7076
7099
  @param {Object} timer Timer object to cancel
@@ -7141,7 +7164,7 @@ Ember.run.cancel = function(timer) {
7141
7164
  then it will be looked up on the passed target.
7142
7165
  @param {Object} [args*] Optional arguments to pass to the timeout.
7143
7166
  @param {Number} wait Number of milliseconds to wait.
7144
- @param {Boolean} immediate Trigger the function on the leading instead
7167
+ @param {Boolean} immediate Trigger the function on the leading instead
7145
7168
  of the trailing edge of the wait interval. Defaults to false.
7146
7169
  @return {Array} Timer information for use in cancelling, see `Ember.run.cancel`.
7147
7170
  */
@@ -11773,6 +11796,8 @@ function _copy(obj, deep, seen, copies) {
11773
11796
  }
11774
11797
  } else if (Ember.Copyable && Ember.Copyable.detect(obj)) {
11775
11798
  ret = obj.copy(deep, seen, copies);
11799
+ } else if (obj instanceof Date) {
11800
+ ret = new Date(obj.getTime());
11776
11801
  } else {
11777
11802
  ret = {};
11778
11803
  for(key in obj) {
@@ -15395,6 +15420,9 @@ var e_get = Ember.get,
15395
15420
  a_slice = [].slice,
15396
15421
  o_create = Ember.create,
15397
15422
  forEach = Ember.EnumerableUtils.forEach,
15423
+ cacheSet = Ember.cacheFor.set,
15424
+ cacheGet = Ember.cacheFor.get,
15425
+ cacheRemove = Ember.cacheFor.remove,
15398
15426
  // Here we explicitly don't allow `@each.foo`; it would require some special
15399
15427
  // testing, but there's no particular reason why it should be disallowed.
15400
15428
  eachPropertyPattern = /^(.*)\.@each\.(.*)/,
@@ -15833,7 +15861,6 @@ function ReduceComputedProperty(options) {
15833
15861
  var cp = this;
15834
15862
 
15835
15863
  this.options = options;
15836
- this._instanceMetas = {};
15837
15864
 
15838
15865
  this._dependentKeys = null;
15839
15866
  // A map of dependentKey -> [itemProperty, ...] that tracks what properties of
@@ -15845,11 +15872,10 @@ function ReduceComputedProperty(options) {
15845
15872
  this.cacheable();
15846
15873
 
15847
15874
  this.recomputeOnce = function(propertyName) {
15848
- // What we really want to do is coalesce by <cp, propertyName>.
15849
- // We need a form of `scheduleOnce` that accepts an arbitrary token to
15850
- // coalesce by, in addition to the target and method.
15851
- Ember.run.once(this, recompute, propertyName);
15875
+ // TODO: Coalesce recomputation by <this, propertyName, cp>.
15876
+ recompute.call(this, propertyName);
15852
15877
  };
15878
+
15853
15879
  var recompute = function(propertyName) {
15854
15880
  var dependentKeys = cp._dependentKeys,
15855
15881
  meta = cp._instanceMeta(this, propertyName),
@@ -15931,19 +15957,15 @@ ReduceComputedProperty.prototype._callbacks = function () {
15931
15957
  };
15932
15958
 
15933
15959
  ReduceComputedProperty.prototype._hasInstanceMeta = function (context, propertyName) {
15934
- var guid = guidFor(context),
15935
- key = guid + ':' + propertyName;
15936
-
15937
- return !!this._instanceMetas[key];
15960
+ return !!metaFor(context).cacheMeta[propertyName];
15938
15961
  };
15939
15962
 
15940
15963
  ReduceComputedProperty.prototype._instanceMeta = function (context, propertyName) {
15941
- var guid = guidFor(context),
15942
- key = guid + ':' + propertyName,
15943
- meta = this._instanceMetas[key];
15964
+ var cacheMeta = metaFor(context).cacheMeta,
15965
+ meta = cacheMeta[propertyName];
15944
15966
 
15945
15967
  if (!meta) {
15946
- meta = this._instanceMetas[key] = new ReduceComputedPropertyInstanceMeta(context, propertyName, this.initialValue());
15968
+ meta = cacheMeta[propertyName] = new ReduceComputedPropertyInstanceMeta(context, propertyName, this.initialValue());
15947
15969
  meta.dependentArraysObserver = new DependentArraysObserver(this._callbacks(), this, meta, context, propertyName, meta.sugarMeta);
15948
15970
  }
15949
15971
 
@@ -18451,8 +18473,12 @@ var get = Ember.get, typeOf = Ember.typeOf;
18451
18473
  property to an `_actions` property at extend time, and adding `_actions`
18452
18474
  to the object's mergedProperties list.
18453
18475
 
18454
- `Ember.ActionHandler` is used internally by Ember in `Ember.View`,
18455
- `Ember.Controller`, and `Ember.Route`.
18476
+ `Ember.ActionHandler` is available on some familiar classes including
18477
+ `Ember.Route`, `Ember.View`, `Ember.Component`, and controllers such as
18478
+ `Ember.Controller` and `Ember.ObjectController`.
18479
+ (Internally the mixin is used by `Ember.CoreView`, `Ember.ControllerMixin`,
18480
+ and `Ember.Route` and available to the above classes through
18481
+ inheritance.)
18456
18482
 
18457
18483
  @class ActionHandler
18458
18484
  @namespace Ember
@@ -21331,5 +21357,863 @@ Ember Runtime
21331
21357
 
21332
21358
  })();
21333
21359
 
21360
+ define("container/container",
21361
+ ["container/inheriting_dict","exports"],
21362
+ function(__dependency1__, __exports__) {
21363
+ "use strict";
21364
+ var InheritingDict = __dependency1__["default"];
21365
+
21366
+ // A lightweight container that helps to assemble and decouple components.
21367
+ // Public api for the container is still in flux.
21368
+ // The public api, specified on the application namespace should be considered the stable api.
21369
+ function Container(parent) {
21370
+ this.parent = parent;
21371
+ this.children = [];
21372
+
21373
+ this.resolver = parent && parent.resolver || function() {};
21374
+
21375
+ this.registry = new InheritingDict(parent && parent.registry);
21376
+ this.cache = new InheritingDict(parent && parent.cache);
21377
+ this.factoryCache = new InheritingDict(parent && parent.factoryCache);
21378
+ this.resolveCache = new InheritingDict(parent && parent.resolveCache);
21379
+ this.typeInjections = new InheritingDict(parent && parent.typeInjections);
21380
+ this.injections = {};
21381
+
21382
+ this.factoryTypeInjections = new InheritingDict(parent && parent.factoryTypeInjections);
21383
+ this.factoryInjections = {};
21384
+
21385
+ this._options = new InheritingDict(parent && parent._options);
21386
+ this._typeOptions = new InheritingDict(parent && parent._typeOptions);
21387
+ }
21388
+
21389
+ Container.prototype = {
21390
+
21391
+ /**
21392
+ @property parent
21393
+ @type Container
21394
+ @default null
21395
+ */
21396
+ parent: null,
21397
+
21398
+ /**
21399
+ @property children
21400
+ @type Array
21401
+ @default []
21402
+ */
21403
+ children: null,
21404
+
21405
+ /**
21406
+ @property resolver
21407
+ @type function
21408
+ */
21409
+ resolver: null,
21410
+
21411
+ /**
21412
+ @property registry
21413
+ @type InheritingDict
21414
+ */
21415
+ registry: null,
21416
+
21417
+ /**
21418
+ @property cache
21419
+ @type InheritingDict
21420
+ */
21421
+ cache: null,
21422
+
21423
+ /**
21424
+ @property typeInjections
21425
+ @type InheritingDict
21426
+ */
21427
+ typeInjections: null,
21428
+
21429
+ /**
21430
+ @property injections
21431
+ @type Object
21432
+ @default {}
21433
+ */
21434
+ injections: null,
21435
+
21436
+ /**
21437
+ @private
21438
+
21439
+ @property _options
21440
+ @type InheritingDict
21441
+ @default null
21442
+ */
21443
+ _options: null,
21444
+
21445
+ /**
21446
+ @private
21447
+
21448
+ @property _typeOptions
21449
+ @type InheritingDict
21450
+ */
21451
+ _typeOptions: null,
21452
+
21453
+ /**
21454
+ Returns a new child of the current container. These children are configured
21455
+ to correctly inherit from the current container.
21456
+
21457
+ @method child
21458
+ @return {Container}
21459
+ */
21460
+ child: function() {
21461
+ var container = new Container(this);
21462
+ this.children.push(container);
21463
+ return container;
21464
+ },
21465
+
21466
+ /**
21467
+ Sets a key-value pair on the current container. If a parent container,
21468
+ has the same key, once set on a child, the parent and child will diverge
21469
+ as expected.
21470
+
21471
+ @method set
21472
+ @param {Object} object
21473
+ @param {String} key
21474
+ @param {any} value
21475
+ */
21476
+ set: function(object, key, value) {
21477
+ object[key] = value;
21478
+ },
21479
+
21480
+ /**
21481
+ Registers a factory for later injection.
21482
+
21483
+ Example:
21484
+
21485
+ ```javascript
21486
+ var container = new Container();
21487
+
21488
+ container.register('model:user', Person, {singleton: false });
21489
+ container.register('fruit:favorite', Orange);
21490
+ container.register('communication:main', Email, {singleton: false});
21491
+ ```
21492
+
21493
+ @method register
21494
+ @param {String} fullName
21495
+ @param {Function} factory
21496
+ @param {Object} options
21497
+ */
21498
+ register: function(fullName, factory, options) {
21499
+ validateFullName(fullName);
21500
+
21501
+ if (factory === undefined) {
21502
+ throw new TypeError('Attempting to register an unknown factory: `' + fullName + '`');
21503
+ }
21504
+
21505
+ var normalizedName = this.normalize(fullName);
21506
+
21507
+ if (this.cache.has(normalizedName)) {
21508
+ throw new Error('Cannot re-register: `' + fullName +'`, as it has already been looked up.');
21509
+ }
21510
+
21511
+ this.registry.set(normalizedName, factory);
21512
+ this._options.set(normalizedName, options || {});
21513
+ },
21514
+
21515
+ /**
21516
+ Unregister a fullName
21517
+
21518
+ ```javascript
21519
+ var container = new Container();
21520
+ container.register('model:user', User);
21521
+
21522
+ container.lookup('model:user') instanceof User //=> true
21523
+
21524
+ container.unregister('model:user')
21525
+ container.lookup('model:user') === undefined //=> true
21526
+ ```
21527
+
21528
+ @method unregister
21529
+ @param {String} fullName
21530
+ */
21531
+ unregister: function(fullName) {
21532
+ validateFullName(fullName);
21533
+
21534
+ var normalizedName = this.normalize(fullName);
21334
21535
 
21536
+ this.registry.remove(normalizedName);
21537
+ this.cache.remove(normalizedName);
21538
+ this.factoryCache.remove(normalizedName);
21539
+ this.resolveCache.remove(normalizedName);
21540
+ this._options.remove(normalizedName);
21541
+ },
21542
+
21543
+ /**
21544
+ Given a fullName return the corresponding factory.
21545
+
21546
+ By default `resolve` will retrieve the factory from
21547
+ its container's registry.
21548
+
21549
+ ```javascript
21550
+ var container = new Container();
21551
+ container.register('api:twitter', Twitter);
21552
+
21553
+ container.resolve('api:twitter') // => Twitter
21554
+ ```
21555
+
21556
+ Optionally the container can be provided with a custom resolver.
21557
+ If provided, `resolve` will first provide the custom resolver
21558
+ the oppertunity to resolve the fullName, otherwise it will fallback
21559
+ to the registry.
21560
+
21561
+ ```javascript
21562
+ var container = new Container();
21563
+ container.resolver = function(fullName) {
21564
+ // lookup via the module system of choice
21565
+ };
21566
+
21567
+ // the twitter factory is added to the module system
21568
+ container.resolve('api:twitter') // => Twitter
21569
+ ```
21570
+
21571
+ @method resolve
21572
+ @param {String} fullName
21573
+ @return {Function} fullName's factory
21574
+ */
21575
+ resolve: function(fullName) {
21576
+ validateFullName(fullName);
21577
+
21578
+ var normalizedName = this.normalize(fullName);
21579
+ var cached = this.resolveCache.get(normalizedName);
21580
+
21581
+ if (cached) { return cached; }
21582
+
21583
+ var resolved = this.resolver(normalizedName) || this.registry.get(normalizedName);
21584
+
21585
+ this.resolveCache.set(normalizedName, resolved);
21586
+
21587
+ return resolved;
21588
+ },
21589
+
21590
+ /**
21591
+ A hook that can be used to describe how the resolver will
21592
+ attempt to find the factory.
21593
+
21594
+ For example, the default Ember `.describe` returns the full
21595
+ class name (including namespace) where Ember's resolver expects
21596
+ to find the `fullName`.
21597
+
21598
+ @method describe
21599
+ @param {String} fullName
21600
+ @return {string} described fullName
21601
+ */
21602
+ describe: function(fullName) {
21603
+ return fullName;
21604
+ },
21605
+
21606
+ /**
21607
+ A hook to enable custom fullName normalization behaviour
21608
+
21609
+ @method normalize
21610
+ @param {String} fullName
21611
+ @return {string} normalized fullName
21612
+ */
21613
+ normalize: function(fullName) {
21614
+ return fullName;
21615
+ },
21616
+
21617
+ /**
21618
+ @method makeToString
21619
+
21620
+ @param {any} factory
21621
+ @param {string} fullName
21622
+ @return {function} toString function
21623
+ */
21624
+ makeToString: function(factory, fullName) {
21625
+ return factory.toString();
21626
+ },
21627
+
21628
+ /**
21629
+ Given a fullName return a corresponding instance.
21630
+
21631
+ The default behaviour is for lookup to return a singleton instance.
21632
+ The singleton is scoped to the container, allowing multiple containers
21633
+ to all have their own locally scoped singletons.
21634
+
21635
+ ```javascript
21636
+ var container = new Container();
21637
+ container.register('api:twitter', Twitter);
21638
+
21639
+ var twitter = container.lookup('api:twitter');
21640
+
21641
+ twitter instanceof Twitter; // => true
21642
+
21643
+ // by default the container will return singletons
21644
+ var twitter2 = container.lookup('api:twitter');
21645
+ twitter instanceof Twitter; // => true
21646
+
21647
+ twitter === twitter2; //=> true
21648
+ ```
21649
+
21650
+ If singletons are not wanted an optional flag can be provided at lookup.
21651
+
21652
+ ```javascript
21653
+ var container = new Container();
21654
+ container.register('api:twitter', Twitter);
21655
+
21656
+ var twitter = container.lookup('api:twitter', { singleton: false });
21657
+ var twitter2 = container.lookup('api:twitter', { singleton: false });
21658
+
21659
+ twitter === twitter2; //=> false
21660
+ ```
21661
+
21662
+ @method lookup
21663
+ @param {String} fullName
21664
+ @param {Object} options
21665
+ @return {any}
21666
+ */
21667
+ lookup: function(fullName, options) {
21668
+ validateFullName(fullName);
21669
+ return lookup(this, this.normalize(fullName), options);
21670
+ },
21671
+
21672
+ /**
21673
+ Given a fullName return the corresponding factory.
21674
+
21675
+ @method lookupFactory
21676
+ @param {String} fullName
21677
+ @return {any}
21678
+ */
21679
+ lookupFactory: function(fullName) {
21680
+ validateFullName(fullName);
21681
+ return factoryFor(this, this.normalize(fullName));
21682
+ },
21683
+
21684
+ /**
21685
+ Given a fullName check if the container is aware of its factory
21686
+ or singleton instance.
21687
+
21688
+ @method has
21689
+ @param {String} fullName
21690
+ @return {Boolean}
21691
+ */
21692
+ has: function(fullName) {
21693
+ validateFullName(fullName);
21694
+ return has(this, this.normalize(fullName));
21695
+ },
21696
+
21697
+ /**
21698
+ Allow registering options for all factories of a type.
21699
+
21700
+ ```javascript
21701
+ var container = new Container();
21702
+
21703
+ // if all of type `connection` must not be singletons
21704
+ container.optionsForType('connection', { singleton: false });
21705
+
21706
+ container.register('connection:twitter', TwitterConnection);
21707
+ container.register('connection:facebook', FacebookConnection);
21708
+
21709
+ var twitter = container.lookup('connection:twitter');
21710
+ var twitter2 = container.lookup('connection:twitter');
21711
+
21712
+ twitter === twitter2; // => false
21713
+
21714
+ var facebook = container.lookup('connection:facebook');
21715
+ var facebook2 = container.lookup('connection:facebook');
21716
+
21717
+ facebook === facebook2; // => false
21718
+ ```
21719
+
21720
+ @method optionsForType
21721
+ @param {String} type
21722
+ @param {Object} options
21723
+ */
21724
+ optionsForType: function(type, options) {
21725
+ if (this.parent) { illegalChildOperation('optionsForType'); }
21726
+
21727
+ this._typeOptions.set(type, options);
21728
+ },
21729
+
21730
+ /**
21731
+ @method options
21732
+ @param {String} type
21733
+ @param {Object} options
21734
+ */
21735
+ options: function(type, options) {
21736
+ this.optionsForType(type, options);
21737
+ },
21738
+
21739
+ /**
21740
+ Used only via `injection`.
21741
+
21742
+ Provides a specialized form of injection, specifically enabling
21743
+ all objects of one type to be injected with a reference to another
21744
+ object.
21745
+
21746
+ For example, provided each object of type `controller` needed a `router`.
21747
+ one would do the following:
21748
+
21749
+ ```javascript
21750
+ var container = new Container();
21751
+
21752
+ container.register('router:main', Router);
21753
+ container.register('controller:user', UserController);
21754
+ container.register('controller:post', PostController);
21755
+
21756
+ container.typeInjection('controller', 'router', 'router:main');
21757
+
21758
+ var user = container.lookup('controller:user');
21759
+ var post = container.lookup('controller:post');
21760
+
21761
+ user.router instanceof Router; //=> true
21762
+ post.router instanceof Router; //=> true
21763
+
21764
+ // both controllers share the same router
21765
+ user.router === post.router; //=> true
21766
+ ```
21767
+
21768
+ @private
21769
+ @method typeInjection
21770
+ @param {String} type
21771
+ @param {String} property
21772
+ @param {String} fullName
21773
+ */
21774
+ typeInjection: function(type, property, fullName) {
21775
+ validateFullName(fullName);
21776
+ if (this.parent) { illegalChildOperation('typeInjection'); }
21777
+
21778
+ var fullNameType = fullName.split(':')[0];
21779
+ if(fullNameType === type) {
21780
+ throw new Error('Cannot inject a `' + fullName + '` on other ' + type + '(s). Register the `' + fullName + '` as a different type and perform the typeInjection.');
21781
+ }
21782
+ addTypeInjection(this.typeInjections, type, property, fullName);
21783
+ },
21784
+
21785
+ /**
21786
+ Defines injection rules.
21787
+
21788
+ These rules are used to inject dependencies onto objects when they
21789
+ are instantiated.
21790
+
21791
+ Two forms of injections are possible:
21792
+
21793
+ * Injecting one fullName on another fullName
21794
+ * Injecting one fullName on a type
21795
+
21796
+ Example:
21797
+
21798
+ ```javascript
21799
+ var container = new Container();
21800
+
21801
+ container.register('source:main', Source);
21802
+ container.register('model:user', User);
21803
+ container.register('model:post', Post);
21804
+
21805
+ // injecting one fullName on another fullName
21806
+ // eg. each user model gets a post model
21807
+ container.injection('model:user', 'post', 'model:post');
21808
+
21809
+ // injecting one fullName on another type
21810
+ container.injection('model', 'source', 'source:main');
21811
+
21812
+ var user = container.lookup('model:user');
21813
+ var post = container.lookup('model:post');
21814
+
21815
+ user.source instanceof Source; //=> true
21816
+ post.source instanceof Source; //=> true
21817
+
21818
+ user.post instanceof Post; //=> true
21819
+
21820
+ // and both models share the same source
21821
+ user.source === post.source; //=> true
21822
+ ```
21823
+
21824
+ @method injection
21825
+ @param {String} factoryName
21826
+ @param {String} property
21827
+ @param {String} injectionName
21828
+ */
21829
+ injection: function(fullName, property, injectionName) {
21830
+ if (this.parent) { illegalChildOperation('injection'); }
21831
+
21832
+ validateFullName(injectionName);
21833
+ var normalizedInjectionName = this.normalize(injectionName);
21834
+
21835
+ if (fullName.indexOf(':') === -1) {
21836
+ return this.typeInjection(fullName, property, normalizedInjectionName);
21837
+ }
21838
+
21839
+ validateFullName(fullName);
21840
+ var normalizedName = this.normalize(fullName);
21841
+
21842
+ addInjection(this.injections, normalizedName, property, normalizedInjectionName);
21843
+ },
21844
+
21845
+
21846
+ /**
21847
+ Used only via `factoryInjection`.
21848
+
21849
+ Provides a specialized form of injection, specifically enabling
21850
+ all factory of one type to be injected with a reference to another
21851
+ object.
21852
+
21853
+ For example, provided each factory of type `model` needed a `store`.
21854
+ one would do the following:
21855
+
21856
+ ```javascript
21857
+ var container = new Container();
21858
+
21859
+ container.register('store:main', SomeStore);
21860
+
21861
+ container.factoryTypeInjection('model', 'store', 'store:main');
21862
+
21863
+ var store = container.lookup('store:main');
21864
+ var UserFactory = container.lookupFactory('model:user');
21865
+
21866
+ UserFactory.store instanceof SomeStore; //=> true
21867
+ ```
21868
+
21869
+ @private
21870
+ @method factoryTypeInjection
21871
+ @param {String} type
21872
+ @param {String} property
21873
+ @param {String} fullName
21874
+ */
21875
+ factoryTypeInjection: function(type, property, fullName) {
21876
+ if (this.parent) { illegalChildOperation('factoryTypeInjection'); }
21877
+
21878
+ addTypeInjection(this.factoryTypeInjections, type, property, this.normalize(fullName));
21879
+ },
21880
+
21881
+ /**
21882
+ Defines factory injection rules.
21883
+
21884
+ Similar to regular injection rules, but are run against factories, via
21885
+ `Container#lookupFactory`.
21886
+
21887
+ These rules are used to inject objects onto factories when they
21888
+ are looked up.
21889
+
21890
+ Two forms of injections are possible:
21891
+
21892
+ * Injecting one fullName on another fullName
21893
+ * Injecting one fullName on a type
21894
+
21895
+ Example:
21896
+
21897
+ ```javascript
21898
+ var container = new Container();
21899
+
21900
+ container.register('store:main', Store);
21901
+ container.register('store:secondary', OtherStore);
21902
+ container.register('model:user', User);
21903
+ container.register('model:post', Post);
21904
+
21905
+ // injecting one fullName on another type
21906
+ container.factoryInjection('model', 'store', 'store:main');
21907
+
21908
+ // injecting one fullName on another fullName
21909
+ container.factoryInjection('model:post', 'secondaryStore', 'store:secondary');
21910
+
21911
+ var UserFactory = container.lookupFactory('model:user');
21912
+ var PostFactory = container.lookupFactory('model:post');
21913
+ var store = container.lookup('store:main');
21914
+
21915
+ UserFactory.store instanceof Store; //=> true
21916
+ UserFactory.secondaryStore instanceof OtherStore; //=> false
21917
+
21918
+ PostFactory.store instanceof Store; //=> true
21919
+ PostFactory.secondaryStore instanceof OtherStore; //=> true
21920
+
21921
+ // and both models share the same source instance
21922
+ UserFactory.store === PostFactory.store; //=> true
21923
+ ```
21924
+
21925
+ @method factoryInjection
21926
+ @param {String} factoryName
21927
+ @param {String} property
21928
+ @param {String} injectionName
21929
+ */
21930
+ factoryInjection: function(fullName, property, injectionName) {
21931
+ if (this.parent) { illegalChildOperation('injection'); }
21932
+
21933
+ var normalizedName = this.normalize(fullName);
21934
+ var normalizedInjectionName = this.normalize(injectionName);
21935
+
21936
+ validateFullName(injectionName);
21937
+
21938
+ if (fullName.indexOf(':') === -1) {
21939
+ return this.factoryTypeInjection(normalizedName, property, normalizedInjectionName);
21940
+ }
21941
+
21942
+ validateFullName(fullName);
21943
+
21944
+ addInjection(this.factoryInjections, normalizedName, property, normalizedInjectionName);
21945
+ },
21946
+
21947
+ /**
21948
+ A depth first traversal, destroying the container, its descendant containers and all
21949
+ their managed objects.
21950
+
21951
+ @method destroy
21952
+ */
21953
+ destroy: function() {
21954
+ for (var i=0, l=this.children.length; i<l; i++) {
21955
+ this.children[i].destroy();
21956
+ }
21957
+
21958
+ this.children = [];
21959
+
21960
+ eachDestroyable(this, function(item) {
21961
+ item.destroy();
21962
+ });
21963
+
21964
+ this.parent = undefined;
21965
+ this.isDestroyed = true;
21966
+ },
21967
+
21968
+ /**
21969
+ @method reset
21970
+ */
21971
+ reset: function() {
21972
+ for (var i=0, l=this.children.length; i<l; i++) {
21973
+ resetCache(this.children[i]);
21974
+ }
21975
+ resetCache(this);
21976
+ }
21977
+ };
21978
+
21979
+ function has(container, fullName){
21980
+ if (container.cache.has(fullName)) {
21981
+ return true;
21982
+ }
21983
+
21984
+ return !!container.resolve(fullName);
21985
+ }
21986
+
21987
+ function lookup(container, fullName, options) {
21988
+ options = options || {};
21989
+
21990
+ if (container.cache.has(fullName) && options.singleton !== false) {
21991
+ return container.cache.get(fullName);
21992
+ }
21993
+
21994
+ var value = instantiate(container, fullName);
21995
+
21996
+ if (value === undefined) { return; }
21997
+
21998
+ if (isSingleton(container, fullName) && options.singleton !== false) {
21999
+ container.cache.set(fullName, value);
22000
+ }
22001
+
22002
+ return value;
22003
+ }
22004
+
22005
+ function illegalChildOperation(operation) {
22006
+ throw new Error(operation + " is not currently supported on child containers");
22007
+ }
22008
+
22009
+ function isSingleton(container, fullName) {
22010
+ var singleton = option(container, fullName, 'singleton');
22011
+
22012
+ return singleton !== false;
22013
+ }
22014
+
22015
+ function buildInjections(container, injections) {
22016
+ var hash = {};
22017
+
22018
+ if (!injections) { return hash; }
22019
+
22020
+ var injection, injectable;
22021
+
22022
+ for (var i=0, l=injections.length; i<l; i++) {
22023
+ injection = injections[i];
22024
+ injectable = lookup(container, injection.fullName);
22025
+
22026
+ if (injectable !== undefined) {
22027
+ hash[injection.property] = injectable;
22028
+ } else {
22029
+ throw new Error('Attempting to inject an unknown injection: `' + injection.fullName + '`');
22030
+ }
22031
+ }
22032
+
22033
+ return hash;
22034
+ }
22035
+
22036
+ function option(container, fullName, optionName) {
22037
+ var options = container._options.get(fullName);
22038
+
22039
+ if (options && options[optionName] !== undefined) {
22040
+ return options[optionName];
22041
+ }
22042
+
22043
+ var type = fullName.split(":")[0];
22044
+ options = container._typeOptions.get(type);
22045
+
22046
+ if (options) {
22047
+ return options[optionName];
22048
+ }
22049
+ }
22050
+
22051
+ function factoryFor(container, fullName) {
22052
+ var name = fullName;
22053
+ var factory = container.resolve(name);
22054
+ var injectedFactory;
22055
+ var cache = container.factoryCache;
22056
+ var type = fullName.split(":")[0];
22057
+
22058
+ if (factory === undefined) { return; }
22059
+
22060
+ if (cache.has(fullName)) {
22061
+ return cache.get(fullName);
22062
+ }
22063
+
22064
+ if (!factory || typeof factory.extend !== 'function' || (!Ember.MODEL_FACTORY_INJECTIONS && type === 'model')) {
22065
+ // TODO: think about a 'safe' merge style extension
22066
+ // for now just fallback to create time injection
22067
+ return factory;
22068
+ } else {
22069
+
22070
+ var injections = injectionsFor(container, fullName);
22071
+ var factoryInjections = factoryInjectionsFor(container, fullName);
22072
+
22073
+ factoryInjections._toString = container.makeToString(factory, fullName);
22074
+
22075
+ injectedFactory = factory.extend(injections);
22076
+ injectedFactory.reopenClass(factoryInjections);
22077
+
22078
+ cache.set(fullName, injectedFactory);
22079
+
22080
+ return injectedFactory;
22081
+ }
22082
+ }
22083
+
22084
+ function injectionsFor(container, fullName) {
22085
+ var splitName = fullName.split(":"),
22086
+ type = splitName[0],
22087
+ injections = [];
22088
+
22089
+ injections = injections.concat(container.typeInjections.get(type) || []);
22090
+ injections = injections.concat(container.injections[fullName] || []);
22091
+
22092
+ injections = buildInjections(container, injections);
22093
+ injections._debugContainerKey = fullName;
22094
+ injections.container = container;
22095
+
22096
+ return injections;
22097
+ }
22098
+
22099
+ function factoryInjectionsFor(container, fullName) {
22100
+ var splitName = fullName.split(":"),
22101
+ type = splitName[0],
22102
+ factoryInjections = [];
22103
+
22104
+ factoryInjections = factoryInjections.concat(container.factoryTypeInjections.get(type) || []);
22105
+ factoryInjections = factoryInjections.concat(container.factoryInjections[fullName] || []);
22106
+
22107
+ factoryInjections = buildInjections(container, factoryInjections);
22108
+ factoryInjections._debugContainerKey = fullName;
22109
+
22110
+ return factoryInjections;
22111
+ }
22112
+
22113
+ function instantiate(container, fullName) {
22114
+ var factory = factoryFor(container, fullName);
22115
+
22116
+ if (option(container, fullName, 'instantiate') === false) {
22117
+ return factory;
22118
+ }
22119
+
22120
+ if (factory) {
22121
+ if (typeof factory.extend === 'function') {
22122
+ // assume the factory was extendable and is already injected
22123
+ return factory.create();
22124
+ } else {
22125
+ // assume the factory was extendable
22126
+ // to create time injections
22127
+ // TODO: support new'ing for instantiation and merge injections for pure JS Functions
22128
+ return factory.create(injectionsFor(container, fullName));
22129
+ }
22130
+ }
22131
+ }
22132
+
22133
+ function eachDestroyable(container, callback) {
22134
+ container.cache.eachLocal(function(key, value) {
22135
+ if (option(container, key, 'instantiate') === false) { return; }
22136
+ callback(value);
22137
+ });
22138
+ }
22139
+
22140
+ function resetCache(container) {
22141
+ container.cache.eachLocal(function(key, value) {
22142
+ if (option(container, key, 'instantiate') === false) { return; }
22143
+ value.destroy();
22144
+ });
22145
+ container.cache.dict = {};
22146
+ }
22147
+
22148
+ function addTypeInjection(rules, type, property, fullName) {
22149
+ var injections = rules.get(type);
22150
+
22151
+ if (!injections) {
22152
+ injections = [];
22153
+ rules.set(type, injections);
22154
+ }
22155
+
22156
+ injections.push({
22157
+ property: property,
22158
+ fullName: fullName
22159
+ });
22160
+ }
22161
+
22162
+ var VALID_FULL_NAME_REGEXP = /^[^:]+.+:[^:]+$/;
22163
+ function validateFullName(fullName) {
22164
+ if (!VALID_FULL_NAME_REGEXP.test(fullName)) {
22165
+ throw new TypeError('Invalid Fullname, expected: `type:name` got: ' + fullName);
22166
+ }
22167
+ }
22168
+
22169
+ function addInjection(rules, factoryName, property, injectionName) {
22170
+ var injections = rules[factoryName] = rules[factoryName] || [];
22171
+ injections.push({ property: property, fullName: injectionName });
22172
+ }
22173
+
22174
+ __exports__["default"] = Container;
22175
+ });define("ember-runtime/ext/rsvp",
22176
+ ["ember-metal/core","ember-metal/logger","exports"],
22177
+ function(__dependency1__, __dependency2__, __exports__) {
22178
+ "use strict";
22179
+ var Ember = __dependency1__["default"];
22180
+ var Logger = __dependency2__["default"];
22181
+
22182
+ var RSVP = requireModule("rsvp");
22183
+ var Test, testModuleName = 'ember-testing/test';
22184
+
22185
+ RSVP.onerrorDefault = function(error) {
22186
+ if (error instanceof Error) {
22187
+ if (Ember.testing) {
22188
+ // ES6TODO: remove when possible
22189
+ if (!Test && Ember.__loader.registry[testModuleName]) {
22190
+ Test = requireModule(testModuleName)['default'];
22191
+ }
22192
+
22193
+ if (Test && Test.adapter) {
22194
+ Test.adapter.exception(error);
22195
+ } else {
22196
+ throw error;
22197
+ }
22198
+ } else {
22199
+ Logger.error(error.stack);
22200
+ Ember.assert(error, false);
22201
+ }
22202
+ }
22203
+ };
22204
+
22205
+ RSVP.on('error', RSVP.onerrorDefault);
22206
+
22207
+ __exports__["default"] = RSVP;
22208
+ });define("ember-runtime/system/container",
22209
+ ["ember-metal/property_set","exports"],
22210
+ function(__dependency1__, __exports__) {
22211
+ "use strict";
22212
+ var set = __dependency1__["default"];
22213
+
22214
+ var Container = requireModule('container')["default"];
22215
+ Container.set = set;
22216
+
22217
+ __exports__["default"] = Container;
22218
+ });
21335
22219
  })();