chore(build): migrated di to TypeScript
This commit is contained in:
		
							parent
							
								
									649e276610
								
							
						
					
					
						commit
						cb87fa0970
					
				| @ -10,6 +10,18 @@ export * from './src/di/decorators'; | ||||
| export {Injector} from './src/di/injector'; | ||||
| export {Binding, ResolvedBinding, Dependency, bind} from './src/di/binding'; | ||||
| export {Key, KeyRegistry} from './src/di/key'; | ||||
| export {KeyMetadataError, NoBindingError, AbstractBindingError, AsyncBindingError, CyclicDependencyError, | ||||
|   InstantiationError, InvalidBindingError, NoAnnotationError} from './src/di/exceptions'; | ||||
| export { | ||||
|   NoBindingError, | ||||
|   AbstractBindingError, | ||||
|   AsyncBindingError, | ||||
|   CyclicDependencyError, | ||||
|   InstantiationError, | ||||
|   InvalidBindingError, | ||||
|   NoAnnotationError | ||||
| } from './src/di/exceptions'; | ||||
| export {OpaqueToken} from './src/di/opaque_token'; | ||||
| 
 | ||||
| // HACK: workaround for Traceur behavior.
 | ||||
| // It expects all transpiled modules to contain this marker.
 | ||||
| // TODO: remove this when we no longer use traceur
 | ||||
| export var __esModule = true; | ||||
| @ -1,6 +1,7 @@ | ||||
| import {ProtoRecord} from './proto_record'; | ||||
| import {BaseException} from "angular2/src/facade/lang"; | ||||
| 
 | ||||
| export class ExpressionChangedAfterItHasBeenChecked extends Error { | ||||
| export class ExpressionChangedAfterItHasBeenChecked extends BaseException { | ||||
|   message:string; | ||||
| 
 | ||||
|   constructor(proto:ProtoRecord, change:any) { | ||||
| @ -14,7 +15,7 @@ export class ExpressionChangedAfterItHasBeenChecked extends Error { | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| export class ChangeDetectionError extends Error { | ||||
| export class ChangeDetectionError extends BaseException { | ||||
|   message:string; | ||||
|   originalException:any; | ||||
|   location:string; | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| import {Injectable} from 'angular2/src/di/annotations_impl'; | ||||
| import {List, ListWrapper, SetWrapper} from "angular2/src/facade/collection"; | ||||
| import {int, NumberWrapper, StringJoiner, StringWrapper} from "angular2/src/facade/lang"; | ||||
| import {int, NumberWrapper, StringJoiner, StringWrapper, BaseException} from "angular2/src/facade/lang"; | ||||
| 
 | ||||
| export const TOKEN_TYPE_CHARACTER  = 1; | ||||
| export const TOKEN_TYPE_IDENTIFIER = 2; | ||||
| @ -176,7 +176,7 @@ export const $RBRACE = 125; | ||||
| const $NBSP   = 160; | ||||
| 
 | ||||
| 
 | ||||
| export class ScannerError extends Error { | ||||
| export class ScannerError extends BaseException { | ||||
|   message:string; | ||||
|   constructor(message) { | ||||
|     super(); | ||||
|  | ||||
| @ -966,7 +966,7 @@ export class ElementInjector extends TreeNode { | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| class OutOfBoundsAccess extends Error { | ||||
| class OutOfBoundsAccess extends BaseException { | ||||
|   message:string; | ||||
|   constructor(index) { | ||||
|     super(); | ||||
| @ -978,7 +978,7 @@ class OutOfBoundsAccess extends Error { | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| class QueryError extends Error { | ||||
| class QueryError extends BaseException { | ||||
|   message:string; | ||||
|   // TODO(rado): pass the names of the active directives.
 | ||||
|   constructor() { | ||||
|  | ||||
| @ -10,4 +10,4 @@ export { | ||||
|   Optional as OptionalAnnotation, | ||||
|   Injectable as InjectableAnnotation, | ||||
|   DependencyAnnotation,  // abstract base class, does not need a decorator
 | ||||
|   } from './annotations_impl'; | ||||
| } from './annotations_impl'; | ||||
| @ -1,5 +1,10 @@ | ||||
| import {CONST} from "angular2/src/facade/lang"; | ||||
| 
 | ||||
| // HACK: workaround for Traceur behavior.
 | ||||
| // It expects all transpiled modules to contain this marker.
 | ||||
| // TODO: remove this when we no longer use traceur
 | ||||
| export var __esModule = true; | ||||
| 
 | ||||
| /** | ||||
|  * A parameter annotation that specifies a dependency. | ||||
|  * | ||||
| @ -11,12 +16,10 @@ import {CONST} from "angular2/src/facade/lang"; | ||||
|  * | ||||
|  * @exportedAs angular2/di_annotations | ||||
|  */ | ||||
| 
 | ||||
| @CONST() | ||||
| export class Inject { | ||||
|   token; | ||||
|   @CONST() | ||||
|   constructor(token) { | ||||
|     this.token = token; | ||||
|   } | ||||
|   constructor(public token) {} | ||||
| } | ||||
| 
 | ||||
| /** | ||||
| @ -32,12 +35,9 @@ export class Inject { | ||||
|  * | ||||
|  * @exportedAs angular2/di_annotations | ||||
|  */ | ||||
| @CONST() | ||||
| export class InjectPromise { | ||||
|   token; | ||||
|   @CONST() | ||||
|   constructor(token) { | ||||
|     this.token = token; | ||||
|   } | ||||
|   constructor(public token) {} | ||||
| } | ||||
| 
 | ||||
| /** | ||||
| @ -53,17 +53,14 @@ export class InjectPromise { | ||||
|  * | ||||
|  * @exportedAs angular2/di_annotations | ||||
|  */ | ||||
| @CONST() | ||||
| export class InjectLazy { | ||||
|   token; | ||||
|   @CONST() | ||||
|   constructor(token) { | ||||
|     this.token = token; | ||||
|   } | ||||
|   constructor(public token) {} | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * A parameter annotation that marks a dependency as optional. {@link Injector} provides `null` if the dependency is not | ||||
|  * found. | ||||
|  * A parameter annotation that marks a dependency as optional. {@link Injector} provides `null` if | ||||
|  * the dependency is not found. | ||||
|  * | ||||
|  * ``` | ||||
|  * class AComponent { | ||||
| @ -75,16 +72,15 @@ export class InjectLazy { | ||||
|  * | ||||
|  * @exportedAs angular2/di_annotations | ||||
|  */ | ||||
| @CONST() | ||||
| export class Optional { | ||||
|   @CONST() | ||||
|   constructor() { | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * `DependencyAnnotation` is used by the framework to extend DI. | ||||
|  * | ||||
|  * Only annotations implementing `DependencyAnnotation` are added to the list of dependency properties. | ||||
|  * Only annotations implementing `DependencyAnnotation` are added to the list of dependency | ||||
|  * properties. | ||||
|  * | ||||
|  * For example: | ||||
|  * | ||||
| @ -108,19 +104,14 @@ export class Optional { | ||||
|  * | ||||
|  * @exportedAs angular2/di_annotations | ||||
|  */ | ||||
| @CONST() | ||||
| export class DependencyAnnotation { | ||||
|   @CONST() | ||||
|   constructor() { | ||||
|   } | ||||
| 
 | ||||
|   get token() { | ||||
|     return null; | ||||
|   } | ||||
|   get token() { return null; } | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * A marker annotation that marks a class as available to `Injector` for creation. Used by tooling for | ||||
|  * generating constructor stubs. | ||||
|  * A marker annotation that marks a class as available to `Injector` for creation. Used by tooling | ||||
|  * for generating constructor stubs. | ||||
|  * | ||||
|  * ``` | ||||
|  * class NeedsService { | ||||
| @ -132,8 +123,6 @@ export class DependencyAnnotation { | ||||
|  * ``` | ||||
|  * @exportedAs angular2/di_annotations | ||||
|  */ | ||||
| @CONST() | ||||
| export class Injectable { | ||||
|   @CONST() | ||||
|   constructor() { | ||||
|   } | ||||
| } | ||||
| @ -2,20 +2,21 @@ import {Type, isBlank, isPresent, CONST} from 'angular2/src/facade/lang'; | ||||
| import {List, MapWrapper, ListWrapper} from 'angular2/src/facade/collection'; | ||||
| import {reflector} from 'angular2/src/reflection/reflection'; | ||||
| import {Key} from './key'; | ||||
| import {Inject, InjectLazy, InjectPromise, Optional, DependencyAnnotation} from './annotations_impl'; | ||||
| import { | ||||
|   Inject, | ||||
|   InjectLazy, | ||||
|   InjectPromise, | ||||
|   Optional, | ||||
|   DependencyAnnotation | ||||
| } from './annotations_impl'; | ||||
| import {NoAnnotationError} from './exceptions'; | ||||
| 
 | ||||
| /** | ||||
|  * @private | ||||
|  */ | ||||
| export class Dependency { | ||||
|   key:Key; | ||||
|   asPromise:boolean; | ||||
|   lazy:boolean; | ||||
|   optional:boolean; | ||||
|   properties:List; | ||||
| 
 | ||||
|   constructor(key:Key, asPromise:boolean, lazy:boolean, optional:boolean, properties:List) { | ||||
|   constructor(public key: Key, public asPromise: boolean, public lazy: boolean, | ||||
|               public optional: boolean, public properties: List<any>) { | ||||
|     this.key = key; | ||||
|     this.asPromise = asPromise; | ||||
|     this.lazy = lazy; | ||||
| @ -23,9 +24,7 @@ export class Dependency { | ||||
|     this.properties = properties; | ||||
|   } | ||||
| 
 | ||||
|   static fromKey(key:Key) { | ||||
|     return new Dependency(key, false, false, false, []); | ||||
|   } | ||||
|   static fromKey(key: Key) { return new Dependency(key, false, false, false, []); } | ||||
| } | ||||
| 
 | ||||
| var _EMPTY_LIST = [];  // TODO: make const when supported
 | ||||
| @ -47,8 +46,8 @@ var _EMPTY_LIST = [];  // TODO: make const when supported | ||||
|  * | ||||
|  * @exportedAs angular2/di | ||||
|  */ | ||||
| @CONST() | ||||
| export class Binding { | ||||
| 
 | ||||
|   /** | ||||
|    * Token used when retrieving this binding. Usually the `Type`. | ||||
|    */ | ||||
| @ -59,7 +58,8 @@ export class Binding { | ||||
|    * | ||||
|    * ## Example | ||||
|    * | ||||
|    * Becuse `toAlias` and `toClass` are often confused, the example contains both use cases for easy comparison. | ||||
|    * Becuse `toAlias` and `toClass` are often confused, the example contains both use cases for easy | ||||
|    * comparison. | ||||
|    * | ||||
|    * ```javascript
 | ||||
|    * | ||||
| @ -83,7 +83,7 @@ export class Binding { | ||||
|    * expect(injectorAlias.get(Vehicle) instanceof Car).toBe(true); | ||||
|    * ``` | ||||
|    */ | ||||
|   toClass:Type; | ||||
|   toClass: Type; | ||||
| 
 | ||||
|   /** | ||||
|    * Binds a key to a value. | ||||
| @ -103,12 +103,13 @@ export class Binding { | ||||
|   /** | ||||
|    * Binds a key to the alias for an existing key. | ||||
|    * | ||||
|    * An alias means that {@link Injector} returns the same instance as if the alias token was used. This is in contrast to | ||||
|    * `toClass` where a separate instance of `toClass` is returned. | ||||
|    * An alias means that {@link Injector} returns the same instance as if the alias token was used. | ||||
|    * This is in contrast to `toClass` where a separate instance of `toClass` is returned. | ||||
|    * | ||||
|    * ## Example | ||||
|    * | ||||
|    * Becuse `toAlias` and `toClass` are often confused the example contains both use cases for easy comparison. | ||||
|    * Becuse `toAlias` and `toClass` are often confused the example contains both use cases for easy | ||||
|    * comparison. | ||||
|    * | ||||
|    * ```javascript
 | ||||
|    * | ||||
| @ -150,7 +151,7 @@ export class Binding { | ||||
|    * expect(injector.get(String)).toEqual('Value: 3'); | ||||
|    * ``` | ||||
|    */ | ||||
|   toFactory:Function; | ||||
|   toFactory: Function; | ||||
| 
 | ||||
|   /** | ||||
|    * Binds a key to a function which computes the value asynchronously. | ||||
| @ -170,17 +171,19 @@ export class Binding { | ||||
|    * injector.asyncGet(String).then((v) => expect(v).toBe('Value: 3')); | ||||
|    * ``` | ||||
|    * | ||||
|    * The interesting thing to note is that event though `Number` has an async factory, the `String` factory | ||||
|    * function takes the resolved value. This shows that the {@link Injector} delays executing the `String` factory | ||||
|    * until after the `Number` is resolved. This can only be done if the `token` is retrieved using the | ||||
|    * `asyncGet` API in the {@link Injector}. | ||||
|    * The interesting thing to note is that event though `Number` has an async factory, the `String` | ||||
|    * factory function takes the resolved value. This shows that the {@link Injector} delays | ||||
|    *executing the | ||||
|    *`String` factory | ||||
|    * until after the `Number` is resolved. This can only be done if the `token` is retrieved using | ||||
|    * the `asyncGet` API in the {@link Injector}. | ||||
|    * | ||||
|    */ | ||||
|   toAsyncFactory:Function; | ||||
|   toAsyncFactory: Function; | ||||
| 
 | ||||
|   /** | ||||
|    * Used in conjunction with `toFactory` or `toAsyncFactory` and specifies a set of dependencies (as `token`s) which | ||||
|    * should be injected into the factory function. | ||||
|    * Used in conjunction with `toFactory` or `toAsyncFactory` and specifies a set of dependencies | ||||
|    * (as `token`s) which should be injected into the factory function. | ||||
|    * | ||||
|    * ## Example | ||||
|    * | ||||
| @ -195,19 +198,11 @@ export class Binding { | ||||
|    * expect(injector.get(String)).toEqual('Value: 3'); | ||||
|    * ``` | ||||
|    */ | ||||
|   dependencies:List; | ||||
|   dependencies: List<any>; | ||||
| 
 | ||||
|   @CONST() | ||||
|   constructor( | ||||
|       token, | ||||
|       { | ||||
|         toClass, | ||||
|         toValue, | ||||
|         toAlias, | ||||
|         toFactory, | ||||
|         toAsyncFactory, | ||||
|         deps | ||||
|       }) { | ||||
|   constructor(token, {toClass, toValue, toAlias, toFactory, toAsyncFactory, deps}: { | ||||
|                          toClass ?: Type, toValue ?: any, toAlias ?: any, toFactory ?: Function, | ||||
|                          toAsyncFactory ?: Function, deps ?: List<any>}) { | ||||
|     this.token = token; | ||||
|     this.toClass = toClass; | ||||
|     this.toValue = toValue; | ||||
| @ -220,10 +215,11 @@ export class Binding { | ||||
|   /** | ||||
|    * Converts the {@link Binding} into {@link ResolvedBinding}. | ||||
|    * | ||||
|    * {@link Injector} internally only uses {@link ResolvedBinding}, {@link Binding} contains convenience binding syntax. | ||||
|    * {@link Injector} internally only uses {@link ResolvedBinding}, {@link Binding} contains | ||||
|    * convenience binding syntax. | ||||
|    */ | ||||
|   resolve(): ResolvedBinding { | ||||
|     var factoryFn:Function; | ||||
|     var factoryFn: Function; | ||||
|     var resolvedDeps; | ||||
|     var isAsync = false; | ||||
|     if (isPresent(this.toClass)) { | ||||
| @ -244,20 +240,16 @@ export class Binding { | ||||
|       resolvedDeps = _EMPTY_LIST; | ||||
|     } | ||||
| 
 | ||||
|     return new ResolvedBinding( | ||||
|       Key.get(this.token), | ||||
|       factoryFn, | ||||
|       resolvedDeps, | ||||
|       isAsync | ||||
|     ); | ||||
|     return new ResolvedBinding(Key.get(this.token), factoryFn, resolvedDeps, isAsync); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * An internal resolved representation of a {@link Binding} used by the {@link Injector}. | ||||
|  * | ||||
|  * A {@link Binding} is resolved when it has a factory function. Binding to a class, alias, or value, are just convenience | ||||
|  * methods, as {@link Injector} only operates on calling factory functions. | ||||
|  * A {@link Binding} is resolved when it has a factory function. Binding to a class, alias, or | ||||
|  * value, are just convenience methods, as {@link Injector} only operates on calling factory | ||||
|  * functions. | ||||
|  * | ||||
|  * @exportedAs angular2/di | ||||
|  */ | ||||
| @ -265,24 +257,25 @@ export class ResolvedBinding { | ||||
|   /** | ||||
|    * A key, usually a `Type`. | ||||
|    */ | ||||
|   key:Key; | ||||
|   key: Key; | ||||
| 
 | ||||
|   /** | ||||
|    * Factory function which can return an instance of an object represented by a key. | ||||
|    */ | ||||
|   factory:Function; | ||||
|   factory: Function; | ||||
| 
 | ||||
|   /** | ||||
|    * Arguments (dependencies) to the `factory` function. | ||||
|    */ | ||||
|   dependencies:List<Dependency>; | ||||
|   dependencies: List<Dependency>; | ||||
| 
 | ||||
|   /** | ||||
|    * Specifies whether the `factory` function returns a `Promise`. | ||||
|    */ | ||||
|   providedAsPromise:boolean; | ||||
|   providedAsPromise: boolean; | ||||
| 
 | ||||
|   constructor(key:Key, factory:Function, dependencies:List<Dependency>, providedAsPromise:boolean) { | ||||
|   constructor(key: Key, factory: Function, dependencies: List<Dependency>, | ||||
|               providedAsPromise: boolean) { | ||||
|     this.key = key; | ||||
|     this.factory = factory; | ||||
|     this.dependencies = dependencies; | ||||
| @ -304,7 +297,7 @@ export class ResolvedBinding { | ||||
|  * | ||||
|  * @exportedAs angular2/di | ||||
|  */ | ||||
| export function bind(token):BindingBuilder { | ||||
| export function bind(token): BindingBuilder { | ||||
|   return new BindingBuilder(token); | ||||
| } | ||||
| 
 | ||||
| @ -316,16 +309,15 @@ export function bind(token):BindingBuilder { | ||||
| export class BindingBuilder { | ||||
|   token; | ||||
| 
 | ||||
|   constructor(token) { | ||||
|     this.token = token; | ||||
|   } | ||||
|   constructor(token) { this.token = token; } | ||||
| 
 | ||||
|   /** | ||||
|    * Binds an interface to an implementation / subclass. | ||||
|    * | ||||
|    * ## Example | ||||
|    * | ||||
|    * Because `toAlias` and `toClass` are often confused, the example contains both use cases for easy comparison. | ||||
|    * Because `toAlias` and `toClass` are often confused, the example contains both use cases for | ||||
|    * easy comparison. | ||||
|    * | ||||
|    * ```javascript
 | ||||
|    * | ||||
| @ -349,9 +341,7 @@ export class BindingBuilder { | ||||
|    * expect(injectorAlias.get(Vehicle) instanceof Car).toBe(true); | ||||
|    * ``` | ||||
|    */ | ||||
|   toClass(type:Type):Binding { | ||||
|     return new Binding(this.token, {toClass: type}); | ||||
|   } | ||||
|   toClass(type: Type): Binding { return new Binding(this.token, {toClass: type}); } | ||||
| 
 | ||||
|   /** | ||||
|    * Binds a key to a value. | ||||
| @ -366,19 +356,18 @@ export class BindingBuilder { | ||||
|    * expect(injector.get(String)).toEqual('Hello'); | ||||
|    * ``` | ||||
|    */ | ||||
|   toValue(value):Binding { | ||||
|     return new Binding(this.token, {toValue: value}); | ||||
|   } | ||||
|   toValue(value): Binding { return new Binding(this.token, {toValue: value}); } | ||||
| 
 | ||||
|   /** | ||||
|    * Binds a key to the alias for an existing key. | ||||
|    * | ||||
|    * An alias means that we will return the same instance as if the alias token was used. (This is in contrast to | ||||
|    * `toClass` where a separet instance of `toClass` will be returned.) | ||||
|    * An alias means that we will return the same instance as if the alias token was used. (This is | ||||
|    * in contrast to `toClass` where a separet instance of `toClass` will be returned.) | ||||
|    * | ||||
|    * ## Example | ||||
|    * | ||||
|    * Becuse `toAlias` and `toClass` are often confused, the example contains both use cases for easy comparison. | ||||
|    * Becuse `toAlias` and `toClass` are often confused, the example contains both use cases for easy | ||||
|    * comparison. | ||||
|    * | ||||
|    * ```javascript
 | ||||
|    * | ||||
| @ -402,9 +391,7 @@ export class BindingBuilder { | ||||
|    * expect(injectorClass.get(Vehicle) instanceof Car).toBe(true); | ||||
|    * ``` | ||||
|    */ | ||||
|   toAlias(aliasToken):Binding { | ||||
|     return new Binding(this.token, {toAlias: aliasToken}); | ||||
|   } | ||||
|   toAlias(aliasToken): Binding { return new Binding(this.token, {toAlias: aliasToken}); } | ||||
| 
 | ||||
|   /** | ||||
|    * Binds a key to a function which computes the value. | ||||
| @ -421,11 +408,8 @@ export class BindingBuilder { | ||||
|    * expect(injector.get(String)).toEqual('Value: 3'); | ||||
|    * ``` | ||||
|    */ | ||||
|   toFactory(factoryFunction:Function, dependencies:List = null):Binding { | ||||
|     return new Binding(this.token, { | ||||
|       toFactory: factoryFunction, | ||||
|       deps: dependencies | ||||
|     }); | ||||
|   toFactory(factoryFunction: Function, dependencies?: List<any>): Binding { | ||||
|     return new Binding(this.token, {toFactory: factoryFunction, deps: dependencies}); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
| @ -445,26 +429,24 @@ export class BindingBuilder { | ||||
|    * injector.asyncGet(String).then((v) => expect(v).toBe('Value: 3')); | ||||
|    * ``` | ||||
|    * | ||||
|    * The interesting thing to note is that event though `Number` has an async factory, the `String` factory | ||||
|    * function takes the resolved value. This shows that the {@link Injector} delays executing of the `String` factory | ||||
|    * until after the `Number` is resolved. This can only be done if the `token` is retrieved using the | ||||
|    * The interesting thing to note is that event though `Number` has an async factory, the `String` | ||||
|    * factory function takes the resolved value. This shows that the {@link Injector} delays | ||||
|    * executing of the `String` factory | ||||
|    * until after the `Number` is resolved. This can only be done if the `token` is retrieved using | ||||
|    * the `asyncGet` API in the {@link Injector}. | ||||
|    */ | ||||
|   toAsyncFactory(factoryFunction:Function, dependencies:List = null):Binding { | ||||
|     return new Binding(this.token, { | ||||
|       toAsyncFactory: factoryFunction, | ||||
|       deps: dependencies | ||||
|     }); | ||||
|   toAsyncFactory(factoryFunction: Function, dependencies?: List<any>): Binding { | ||||
|     return new Binding(this.token, {toAsyncFactory: factoryFunction, deps: dependencies}); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| function _constructDependencies(factoryFunction:Function, dependencies:List) { | ||||
| function _constructDependencies(factoryFunction: Function, dependencies: List<any>) { | ||||
|   return isBlank(dependencies) ? | ||||
|     _dependenciesFor(factoryFunction) : | ||||
|     ListWrapper.map(dependencies, (t) => Dependency.fromKey(Key.get(t))); | ||||
|              _dependenciesFor(factoryFunction) : | ||||
|              ListWrapper.map(dependencies, (t) => Dependency.fromKey(Key.get(t))); | ||||
| } | ||||
| 
 | ||||
| function _dependenciesFor(typeOrFunc):List { | ||||
| function _dependenciesFor(typeOrFunc): List<any> { | ||||
|   var params = reflector.parameters(typeOrFunc); | ||||
|   if (isBlank(params)) return []; | ||||
|   if (ListWrapper.any(params, (p) => isBlank(p))) throw new NoAnnotationError(typeOrFunc); | ||||
| @ -500,10 +482,9 @@ function _extractToken(typeOrFunc, annotations) { | ||||
| 
 | ||||
|     } else if (paramAnnotation instanceof DependencyAnnotation) { | ||||
|       if (isPresent(paramAnnotation.token)) { | ||||
|        token = paramAnnotation.token; | ||||
|         token = paramAnnotation.token; | ||||
|       } | ||||
|       ListWrapper.push(depProps, paramAnnotation); | ||||
| 
 | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
| @ -514,6 +495,6 @@ function _extractToken(typeOrFunc, annotations) { | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| function _createDependency(token, asPromise, lazy, optional, depProps):Dependency { | ||||
| function _createDependency(token, asPromise, lazy, optional, depProps): Dependency { | ||||
|   return new Dependency(Key.get(token), asPromise, lazy, optional, depProps); | ||||
| } | ||||
| @ -3,7 +3,8 @@ import { | ||||
|   InjectPromiseAnnotation, | ||||
|   InjectLazyAnnotation, | ||||
|   OptionalAnnotation, | ||||
|   InjectableAnnotation} from './annotations'; | ||||
|   InjectableAnnotation | ||||
| } from './annotations'; | ||||
| import {makeDecorator, makeParamDecorator} from '../util/decorators'; | ||||
| 
 | ||||
| export var Inject = makeParamDecorator(InjectAnnotation); | ||||
| @ -1,9 +1,9 @@ | ||||
| import {ListWrapper, List} from 'angular2/src/facade/collection'; | ||||
| import {stringify} from 'angular2/src/facade/lang'; | ||||
| import {stringify, BaseException} from 'angular2/src/facade/lang'; | ||||
| 
 | ||||
| function findFirstClosedCycle(keys:List):List { | ||||
| function findFirstClosedCycle(keys: List<any>): List<any> { | ||||
|   var res = []; | ||||
|   for(var i = 0; i < keys.length; ++i) { | ||||
|   for (var i = 0; i < keys.length; ++i) { | ||||
|     if (ListWrapper.contains(res, keys[i])) { | ||||
|       ListWrapper.push(res, keys[i]); | ||||
|       return res; | ||||
| @ -14,7 +14,7 @@ function findFirstClosedCycle(keys:List):List { | ||||
|   return res; | ||||
| } | ||||
| 
 | ||||
| function constructResolvingPath(keys:List):string { | ||||
| function constructResolvingPath(keys: List<any>): string { | ||||
|   if (keys.length > 1) { | ||||
|     var reversed = findFirstClosedCycle(ListWrapper.reversed(keys)); | ||||
|     var tokenStrs = ListWrapper.map(reversed, (k) => stringify(k.token)); | ||||
| @ -30,12 +30,13 @@ function constructResolvingPath(keys:List):string { | ||||
|  * | ||||
|  * @exportedAs angular2/di_errors | ||||
|  */ | ||||
| export class AbstractBindingError extends Error { | ||||
|   keys:List; | ||||
|   constructResolvingMessage:Function; | ||||
|   message; | ||||
| export class AbstractBindingError extends BaseException { | ||||
|   name: string; | ||||
|   message: string; | ||||
|   keys: List<any>; | ||||
|   constructResolvingMessage: Function; | ||||
|   // TODO(tbosch): Can't do key:Key as this results in a circular dependency!
 | ||||
|   constructor(key, constructResolvingMessage:Function) { | ||||
|   constructor(key, constructResolvingMessage: Function) { | ||||
|     super(); | ||||
|     this.keys = [key]; | ||||
|     this.constructResolvingMessage = constructResolvingMessage; | ||||
| @ -43,26 +44,24 @@ export class AbstractBindingError extends Error { | ||||
|   } | ||||
| 
 | ||||
|   // TODO(tbosch): Can't do key:Key as this results in a circular dependency!
 | ||||
|   addKey(key):void { | ||||
|   addKey(key): void { | ||||
|     ListWrapper.push(this.keys, key); | ||||
|     this.message = this.constructResolvingMessage(this.keys); | ||||
|   } | ||||
| 
 | ||||
|   toString():string { | ||||
|     return this.message; | ||||
|   } | ||||
|   toString(): string { return this.message; } | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * Thrown when trying to retrieve a dependency by `Key` from {@link Injector}, but the {@link Injector} does not have a | ||||
|  * {@link Binding} for {@link Key}. | ||||
|  * Thrown when trying to retrieve a dependency by `Key` from {@link Injector}, but the | ||||
|  * {@link Injector} does not have a {@link Binding} for {@link Key}. | ||||
|  * | ||||
|  * @exportedAs angular2/di_errors | ||||
|  */ | ||||
| export class NoBindingError extends AbstractBindingError { | ||||
|   // TODO(tbosch): Can't do key:Key as this results in a circular dependency!
 | ||||
|   constructor(key) { | ||||
|     super(key, function (keys:List) { | ||||
|     super(key, function (keys:List<any>) { | ||||
|       var first = stringify(ListWrapper.first(keys).token); | ||||
|       return `No provider for ${first}!${constructResolvingPath(keys)}`; | ||||
|     }); | ||||
| @ -88,18 +87,17 @@ export class NoBindingError extends AbstractBindingError { | ||||
|  * }).toThrowError(AsycBindingError); | ||||
|  * ``` | ||||
|  * | ||||
|  * The above example throws because `String` depends on `Number` which is async. If any binding in the dependency | ||||
|  * graph is async then the graph can only be retrieved using the `asyncGet` API. | ||||
|  * The above example throws because `String` depends on `Number` which is async. If any binding in | ||||
|  * the dependency graph is async then the graph can only be retrieved using the `asyncGet` API. | ||||
|  * | ||||
|  * @exportedAs angular2/di_errors | ||||
|  */ | ||||
| export class AsyncBindingError extends AbstractBindingError { | ||||
|   // TODO(tbosch): Can't do key:Key as this results in a circular dependency!
 | ||||
|   constructor(key) { | ||||
|     super(key, function (keys:List) { | ||||
|     super(key, function (keys:List<any>) { | ||||
|       var first = stringify(ListWrapper.first(keys).token); | ||||
|       return `Cannot instantiate ${first} synchronously. ` + | ||||
|         `It is provided as a promise!${constructResolvingPath(keys)}`; | ||||
|       return `Cannot instantiate ${first} synchronously. It is provided as a promise!${constructResolvingPath(keys)}`; | ||||
|     }); | ||||
|   } | ||||
| } | ||||
| @ -125,7 +123,7 @@ export class AsyncBindingError extends AbstractBindingError { | ||||
| export class CyclicDependencyError extends AbstractBindingError { | ||||
|   // TODO(tbosch): Can't do key:Key as this results in a circular dependency!
 | ||||
|   constructor(key) { | ||||
|     super(key, function (keys:List) { | ||||
|     super(key, function (keys:List<any>) { | ||||
|       return `Cannot instantiate cyclic dependency!${constructResolvingPath(keys)}`; | ||||
|     }); | ||||
|   } | ||||
| @ -134,8 +132,8 @@ export class CyclicDependencyError extends AbstractBindingError { | ||||
| /** | ||||
|  * Thrown when a constructing type returns with an Error. | ||||
|  * | ||||
|  * The `InstantiationError` class contains the original error plus the dependency graph which caused this object to be | ||||
|  * instantiated. | ||||
|  * The `InstantiationError` class contains the original error plus the dependency graph which caused | ||||
|  * this object to be instantiated. | ||||
|  * | ||||
|  * @exportedAs angular2/di_errors | ||||
|  */ | ||||
| @ -144,10 +142,9 @@ export class InstantiationError extends AbstractBindingError { | ||||
|   causeKey; | ||||
|   // TODO(tbosch): Can't do key:Key as this results in a circular dependency!
 | ||||
|   constructor(cause, key) { | ||||
|     super(key, function (keys:List) { | ||||
|     super(key, function (keys:List<any>) { | ||||
|       var first = stringify(ListWrapper.first(keys).token); | ||||
|       return `Error during instantiation of ${first}!${constructResolvingPath(keys)}.` + | ||||
|         ` ORIGINAL ERROR: ${cause}`; | ||||
|       return `Error during instantiation of ${first}!${constructResolvingPath(keys)}. ORIGINAL ERROR: ${cause}`; | ||||
|     }); | ||||
|     this.cause = cause; | ||||
|     this.causeKey = key; | ||||
| @ -155,39 +152,38 @@ export class InstantiationError extends AbstractBindingError { | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * Thrown when an object other then {@link Binding} (or `Type`) is passed to {@link Injector} creation. | ||||
|  * Thrown when an object other then {@link Binding} (or `Type`) is passed to {@link Injector} | ||||
|  * creation. | ||||
|  * | ||||
|  * @exportedAs angular2/di_errors | ||||
|  */ | ||||
| export class InvalidBindingError extends Error { | ||||
|   message:string; | ||||
| export class InvalidBindingError extends BaseException { | ||||
|   message: string; | ||||
|   constructor(binding) { | ||||
|     super(); | ||||
|     this.message = `Invalid binding - only instances of Binding and Type are allowed, got: ${binding}`; | ||||
|     this.message = "Invalid binding - only instances of Binding and Type are allowed, got: " + | ||||
|                    binding.toString(); | ||||
|   } | ||||
| 
 | ||||
|   toString():string { | ||||
|     return this.message; | ||||
|   } | ||||
|   toString(): string { return this.message; } | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * Thrown when the class has no annotation information. | ||||
|  * | ||||
|  * Lack of annotation information prevents the {@link Injector} from determining which dependencies need to be injected into | ||||
|  * the constructor. | ||||
|  * Lack of annotation information prevents the {@link Injector} from determining which dependencies | ||||
|  * need to be injected into the constructor. | ||||
|  * | ||||
|  * @exportedAs angular2/di_errors | ||||
|  */ | ||||
| export class NoAnnotationError extends Error { | ||||
|   message:string; | ||||
| export class NoAnnotationError extends BaseException { | ||||
|   name: string; | ||||
|   message: string; | ||||
|   constructor(typeOrFunc) { | ||||
|     super(); | ||||
|     this.message = `Cannot resolve all parameters for ${stringify(typeOrFunc)}.` + | ||||
|       ` Make sure they all have valid type or annotations.`; | ||||
|     this.message = "Cannot resolve all parameters for " + stringify(typeOrFunc) + ". " + | ||||
|                    'Make sure they all have valid type or annotations.'; | ||||
|   } | ||||
| 
 | ||||
|   toString():string { | ||||
|     return this.message; | ||||
|   } | ||||
|   toString(): string { return this.message; } | ||||
| } | ||||
| @ -1,31 +1,37 @@ | ||||
| /// <reference path="../../typings/es6-promise/es6-promise.d.ts" />
 | ||||
| 
 | ||||
| import {Map, List, MapWrapper, ListWrapper} from 'angular2/src/facade/collection'; | ||||
| import {ResolvedBinding, Binding, BindingBuilder, bind} from './binding'; | ||||
| import {AbstractBindingError, NoBindingError, AsyncBindingError, CyclicDependencyError, | ||||
|   InstantiationError, InvalidBindingError} from './exceptions'; | ||||
| import { | ||||
|   AbstractBindingError, | ||||
|   NoBindingError, | ||||
|   AsyncBindingError, | ||||
|   CyclicDependencyError, | ||||
|   InstantiationError, | ||||
|   InvalidBindingError | ||||
| } from './exceptions'; | ||||
| import {FunctionWrapper, Type, isPresent, isBlank} from 'angular2/src/facade/lang'; | ||||
| import {Promise, PromiseWrapper} from 'angular2/src/facade/async'; | ||||
| import {PromiseWrapper, Promise} from 'angular2/src/facade/async'; | ||||
| import {Key} from './key'; | ||||
| 
 | ||||
| var _constructing = new Object(); | ||||
| var _notFound = new Object(); | ||||
| 
 | ||||
| class _Waiting { | ||||
|   promise:Promise; | ||||
|   constructor(promise:Promise) { | ||||
|     this.promise = promise; | ||||
|   } | ||||
|   promise: Promise<any>; | ||||
|   constructor(promise: Promise<any>) { this.promise = promise; } | ||||
| } | ||||
| function _isWaiting(obj):boolean { | ||||
| function _isWaiting(obj): boolean { | ||||
|   return obj instanceof _Waiting; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /** | ||||
|  * A dependency injection container used for resolving dependencies. | ||||
|  * | ||||
|  * An `Injector` is a replacement for a `new` operator, which can automatically resolve the constructor dependencies. | ||||
|  * In typical use, application code asks for the dependencies in the constructor and they are resolved by the | ||||
|  * `Injector`. | ||||
|  * An `Injector` is a replacement for a `new` operator, which can automatically resolve the | ||||
|  * constructor dependencies. | ||||
|  * In typical use, application code asks for the dependencies in the constructor and they are | ||||
|  * resolved by the `Injector`. | ||||
|  * | ||||
|  * ## Example: | ||||
|  * | ||||
| @ -36,14 +42,15 @@ function _isWaiting(obj):boolean { | ||||
|  * } | ||||
|  * | ||||
|  * class Car { | ||||
|  *   constructor(@Inject(Engine) engine) { | ||||
|  *   } | ||||
|  * 	constructor(@Inject(Engine) engine) { | ||||
|  * 	} | ||||
|  * } | ||||
|  * | ||||
|  * ``` | ||||
|  * | ||||
|  * Next we need to write the code that creates and instantiates the `Injector`. We then ask for the `root` object, | ||||
|  * `Car`, so that the `Injector` can recursively build all of that object's dependencies. | ||||
|  * Next we need to write the code that creates and instantiates the `Injector`. We then ask for the | ||||
|  * `root` object, `Car`, so that the `Injector` can recursively build all of that object's | ||||
|  *dependencies. | ||||
|  * | ||||
|  * ```javascript
 | ||||
|  * main() { | ||||
| @ -53,71 +60,79 @@ function _isWaiting(obj):boolean { | ||||
|  *   var car = injector.get(Car); | ||||
|  * } | ||||
|  * ``` | ||||
|  * Notice that we don't use the `new` operator because we explicitly want to have the `Injector` resolve all of the | ||||
|  * object's dependencies automatically. | ||||
|  * Notice that we don't use the `new` operator because we explicitly want to have the `Injector` | ||||
|  * resolve all of the object's dependencies automatically. | ||||
|  * | ||||
|  * @exportedAs angular2/di | ||||
|  */ | ||||
| export class Injector { | ||||
|   _bindings:List; | ||||
|   _instances:List; | ||||
|   _parent:Injector; | ||||
|   _defaultBindings:boolean; | ||||
|   _bindings: List<any>; | ||||
|   _instances: List<any>; | ||||
|   _parent: Injector; | ||||
|   _defaultBindings: boolean; | ||||
|   _asyncStrategy: _AsyncInjectorStrategy; | ||||
|   _syncStrategy:_SyncInjectorStrategy; | ||||
|   _syncStrategy: _SyncInjectorStrategy; | ||||
| 
 | ||||
|   /** | ||||
|    * Turns a list of binding definitions into an internal resolved list of resolved bindings. | ||||
|    * | ||||
|    * A resolution is a process of flattening multiple nested lists and converting individual bindings into a | ||||
|    * list of {@link ResolvedBinding}s. The resolution can be cached by `resolve` for the {@link Injector} for | ||||
|    * performance-sensitive code. | ||||
|    * A resolution is a process of flattening multiple nested lists and converting individual | ||||
|    * bindings into a list of {@link ResolvedBinding}s. The resolution can be cached by `resolve` | ||||
|    * for the {@link Injector} for performance-sensitive code. | ||||
|    * | ||||
|    * @param `bindings` can be a list of `Type`, {@link Binding}, {@link ResolvedBinding}, or a recursive | ||||
|    * list of more bindings. | ||||
|    * @param `bindings` can be a list of `Type`, {@link Binding}, {@link ResolvedBinding}, or a | ||||
|    * recursive list of more bindings. | ||||
|    * | ||||
|    * The returned list is sparse, indexed by `id` for the {@link Key}. It is generally not useful to application code | ||||
|    * other than for passing it to {@link Injector} functions that require resolved binding lists, such as | ||||
|    * The returned list is sparse, indexed by `id` for the {@link Key}. It is generally not useful to | ||||
|    *application code | ||||
|    * other than for passing it to {@link Injector} functions that require resolved binding lists, | ||||
|    *such as | ||||
|    * `fromResolvedBindings` and `createChildFromResolved`. | ||||
|    */ | ||||
|   static resolve(bindings:List/*<ResolvedBinding|Binding|Type|List>*/):List<ResolvedBinding> { | ||||
|   static resolve(bindings: List<any>): List<ResolvedBinding> { | ||||
|     var resolvedBindings = _resolveBindings(bindings); | ||||
|     var flatten = _flattenBindings(resolvedBindings, MapWrapper.create()); | ||||
|     return _createListOfBindings(flatten); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Resolves bindings and creates an injector based on those bindings. This function is slower than the | ||||
|    * corresponding `fromResolvedBindings` because it needs to resolve bindings first. See `resolve` for the | ||||
|    * {@link Injector}. | ||||
|    * Resolves bindings and creates an injector based on those bindings. This function is slower than | ||||
|    * the corresponding `fromResolvedBindings` because it needs to resolve bindings first. See | ||||
|    *`resolve` | ||||
|    * for the {@link Injector}. | ||||
|    * | ||||
|    * Prefer `fromResolvedBindings` in performance-critical code that creates lots of injectors. | ||||
|    * | ||||
|    * @param `bindings` can be a list of `Type`, {@link Binding}, {@link ResolvedBinding}, or a recursive list of more | ||||
|    * @param `bindings` can be a list of `Type`, {@link Binding}, {@link ResolvedBinding}, or a | ||||
|    *recursive list of more | ||||
|    * bindings. | ||||
|    * @param `defaultBindings` Setting to true will auto-create bindings. | ||||
|    */ | ||||
|   static resolveAndCreate(bindings:List/*<ResolvedBinding|Binding|Type|List>*/, {defaultBindings=false}={}): Injector { | ||||
|   static resolveAndCreate(bindings: List<any>, {defaultBindings = false}: any = {}): Injector { | ||||
|     return new Injector(Injector.resolve(bindings), null, defaultBindings); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Creates an injector from previously resolved bindings. This bypasses resolution and flattening. This API is the | ||||
|    * recommended way to construct injectors in performance-sensitive parts. | ||||
|    * Creates an injector from previously resolved bindings. This bypasses resolution and flattening. | ||||
|    * This API is the recommended way to construct injectors in performance-sensitive parts. | ||||
|    * | ||||
|    * @param `bindings` A sparse list of {@link ResolvedBinding}s. See `resolve` for the {@link Injector}. | ||||
|    * @param `bindings` A sparse list of {@link ResolvedBinding}s. See `resolve` for the {@link | ||||
|    *Injector}. | ||||
|    * @param `defaultBindings` Setting to true will auto-create bindings. | ||||
|    */ | ||||
|   static fromResolvedBindings(bindings:List<ResolvedBinding>, {defaultBindings=false}={}): Injector { | ||||
|   static fromResolvedBindings(bindings: List<ResolvedBinding>, | ||||
|                               {defaultBindings = false}: any = {}): Injector { | ||||
|     return new Injector(bindings, null, defaultBindings); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * @param `bindings` A sparse list of {@link ResolvedBinding}s. See `resolve` for the {@link Injector}. | ||||
|    * @param `bindings` A sparse list of {@link ResolvedBinding}s. See `resolve` for the {@link | ||||
|    * Injector}. | ||||
|    * @param `parent` Parent Injector or `null` if root Injector. | ||||
|    * @param `defaultBindings` Setting to true will auto-create bindings. (Only use with root injector.) | ||||
|    * @param `defaultBindings` Setting to true will auto-create bindings. (Only use with root | ||||
|    * injector.) | ||||
|    */ | ||||
|   constructor(bindings:List<ResolvedBinding>, parent:Injector, defaultBindings:boolean) { | ||||
|   constructor(bindings: List<ResolvedBinding>, parent: Injector, defaultBindings: boolean) { | ||||
|     this._bindings = bindings; | ||||
|     this._instances = this._createInstances(); | ||||
|     this._parent = parent; | ||||
| @ -129,12 +144,11 @@ export class Injector { | ||||
|   /** | ||||
|    * Retrieves an instance from the injector. | ||||
|    * | ||||
|    * @param `token`: usually the `Type` of an object. (Same as the token used while setting up a binding). | ||||
|    * @param `token`: usually the `Type` of an object. (Same as the token used while setting up a | ||||
|    *binding). | ||||
|    * @returns an instance represented by the token. Throws if not found. | ||||
|    */ | ||||
|   get(token) { | ||||
|     return this._getByKey(Key.get(token), false, false, false); | ||||
|   } | ||||
|   get(token) { return this._getByKey(Key.get(token), false, false, false); } | ||||
| 
 | ||||
| 
 | ||||
|   /** | ||||
| @ -143,9 +157,7 @@ export class Injector { | ||||
|    * @param `token`: usually a `Type`. (Same as the token used while setting up a binding). | ||||
|    * @returns an instance represented by the token. Returns `null` if not found. | ||||
|    */ | ||||
|   getOptional(token) { | ||||
|     return this._getByKey(Key.get(token), false, false, true); | ||||
|   } | ||||
|   getOptional(token) { return this._getByKey(Key.get(token), false, false, true); } | ||||
| 
 | ||||
|   /** | ||||
|    * Retrieves an instance from the injector asynchronously. Used with asynchronous bindings. | ||||
| @ -153,40 +165,37 @@ export class Injector { | ||||
|    * @param `token`: usually a `Type`. (Same as token used while setting up a binding). | ||||
|    * @returns a `Promise` which resolves to the instance represented by the token. | ||||
|    */ | ||||
|   asyncGet(token):Promise { | ||||
|     return this._getByKey(Key.get(token), true, false, false); | ||||
|   } | ||||
|   asyncGet(token): Promise<any> { return this._getByKey(Key.get(token), true, false, false); } | ||||
| 
 | ||||
|   /** | ||||
|    * Creates a child injector and loads a new set of bindings into it. | ||||
|    * | ||||
|    * A resolution is a process of flattening multiple nested lists and converting individual bindings into a | ||||
|    * list of {@link ResolvedBinding}s. The resolution can be cached by `resolve` for the {@link Injector} for | ||||
|    * performance-sensitive code. | ||||
|    * A resolution is a process of flattening multiple nested lists and converting individual | ||||
|    * bindings into a list of {@link ResolvedBinding}s. The resolution can be cached by `resolve` | ||||
|    * for the {@link Injector} for performance-sensitive code. | ||||
|    * | ||||
|    * @param `bindings` can be a list of `Type`, {@link Binding}, {@link ResolvedBinding}, or a recursive | ||||
|    * list of more bindings. | ||||
|    * @param `bindings` can be a list of `Type`, {@link Binding}, {@link ResolvedBinding}, or a | ||||
|    * recursive list of more bindings. | ||||
|    * | ||||
|    */ | ||||
|   resolveAndCreateChild(bindings:List/*<ResolvedBinding|Binding|Type|List>*/):Injector { | ||||
|   resolveAndCreateChild(bindings: List<any>): Injector { | ||||
|     return new Injector(Injector.resolve(bindings), this, false); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Creates a child injector and loads a new set of {@link ResolvedBinding}s into it. | ||||
|    * | ||||
|    * @param `bindings`: A sparse list of  {@link ResolvedBinding}s. See `resolve` for the {@link Injector}. | ||||
|    * @param `bindings`: A sparse list of {@link ResolvedBinding}s. | ||||
|    * See `resolve` for the {@link Injector}. | ||||
|    * @returns a new child {@link Injector}. | ||||
|    */ | ||||
|   createChildFromResolved(bindings:List<ResolvedBinding>):Injector { | ||||
|   createChildFromResolved(bindings: List<ResolvedBinding>): Injector { | ||||
|     return new Injector(bindings, this, false); | ||||
|   } | ||||
| 
 | ||||
|   _createInstances():List { | ||||
|     return ListWrapper.createFixedSize(Key.numberOfKeys + 1); | ||||
|   } | ||||
|   _createInstances(): List<any> { return ListWrapper.createFixedSize(Key.numberOfKeys + 1); } | ||||
| 
 | ||||
|   _getByKey(key:Key, returnPromise:boolean, returnLazy:boolean, optional:boolean) { | ||||
|   _getByKey(key: Key, returnPromise: boolean, returnLazy: boolean, optional: boolean) { | ||||
|     if (returnLazy) { | ||||
|       return () => this._getByKey(key, returnPromise, false, optional); | ||||
|     } | ||||
| @ -210,7 +219,7 @@ export class Injector { | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   _resolveDependencies(key:Key, binding:ResolvedBinding, forceAsync:boolean):List { | ||||
|   _resolveDependencies(key: Key, binding: ResolvedBinding, forceAsync: boolean): List<any> { | ||||
|     try { | ||||
|       var getDependency = d => this._getByKey(d.key, forceAsync || d.asPromise, d.lazy, d.optional); | ||||
|       return ListWrapper.map(binding.dependencies, getDependency); | ||||
| @ -221,44 +230,35 @@ export class Injector { | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   _getInstance(key:Key) { | ||||
|   _getInstance(key: Key) { | ||||
|     if (this._instances.length <= key.id) return null; | ||||
|     return ListWrapper.get(this._instances, key.id); | ||||
|   } | ||||
| 
 | ||||
|   _setInstance(key:Key, obj):void { | ||||
|     ListWrapper.set(this._instances, key.id, obj); | ||||
|   } | ||||
|   _setInstance(key: Key, obj): void { ListWrapper.set(this._instances, key.id, obj); } | ||||
| 
 | ||||
|   _getBinding(key:Key) { | ||||
|     var binding = this._bindings.length <= key.id ? | ||||
|       null : | ||||
|       ListWrapper.get(this._bindings, key.id); | ||||
|   _getBinding(key: Key) { | ||||
|     var binding = this._bindings.length <= key.id ? null : ListWrapper.get(this._bindings, key.id); | ||||
| 
 | ||||
|     if (isBlank(binding) && this._defaultBindings) { | ||||
|       return bind(key.token).toClass(key.token).resolve(); | ||||
|       var token: any = key.token; | ||||
|       return bind(key.token).toClass(token).resolve(); | ||||
|     } else { | ||||
|       return binding; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   _markAsConstructing(key:Key):void { | ||||
|     this._setInstance(key, _constructing); | ||||
|   } | ||||
|   _markAsConstructing(key: Key): void { this._setInstance(key, _constructing); } | ||||
| 
 | ||||
|   _clear(key:Key):void { | ||||
|     this._setInstance(key, null); | ||||
|   } | ||||
|   _clear(key: Key): void { this._setInstance(key, null); } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| class _SyncInjectorStrategy { | ||||
|   injector:Injector; | ||||
|   constructor(injector:Injector) { | ||||
|     this.injector = injector; | ||||
|   } | ||||
|   injector: Injector; | ||||
|   constructor(injector: Injector) { this.injector = injector; } | ||||
| 
 | ||||
|   readFromCache(key:Key) { | ||||
|   readFromCache(key: Key) { | ||||
|     if (key.token === Injector) { | ||||
|       return this.injector; | ||||
|     } | ||||
| @ -274,20 +274,20 @@ class _SyncInjectorStrategy { | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   instantiate(key:Key) { | ||||
|   instantiate(key: Key) { | ||||
|     var binding = this.injector._getBinding(key); | ||||
|     if (isBlank(binding)) return _notFound; | ||||
| 
 | ||||
|     if (binding.providedAsPromise) throw new AsyncBindingError(key); | ||||
| 
 | ||||
|     //add a marker so we can detect cyclic dependencies
 | ||||
|     // add a marker so we can detect cyclic dependencies
 | ||||
|     this.injector._markAsConstructing(key); | ||||
| 
 | ||||
|     var deps = this.injector._resolveDependencies(key, binding, false); | ||||
|     return this._createInstance(key, binding, deps); | ||||
|   } | ||||
| 
 | ||||
|   _createInstance(key:Key, binding:ResolvedBinding, deps:List) { | ||||
|   _createInstance(key: Key, binding: ResolvedBinding, deps: List<any>) { | ||||
|     try { | ||||
|       var instance = FunctionWrapper.apply(binding.factory, deps); | ||||
|       this.injector._setInstance(key, instance); | ||||
| @ -301,12 +301,10 @@ class _SyncInjectorStrategy { | ||||
| 
 | ||||
| 
 | ||||
| class _AsyncInjectorStrategy { | ||||
|   injector:Injector; | ||||
|   constructor(injector:Injector) { | ||||
|     this.injector = injector; | ||||
|   } | ||||
|   injector: Injector; | ||||
|   constructor(injector: Injector) { this.injector = injector; } | ||||
| 
 | ||||
|   readFromCache(key:Key) { | ||||
|   readFromCache(key: Key) { | ||||
|     if (key.token === Injector) { | ||||
|       return PromiseWrapper.resolve(this.injector); | ||||
|     } | ||||
| @ -324,31 +322,30 @@ class _AsyncInjectorStrategy { | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   instantiate(key:Key) /* Promise?? */ { | ||||
|   instantiate(key: Key) /* Promise?? */ { | ||||
|     var binding = this.injector._getBinding(key); | ||||
|     if (isBlank(binding)) return _notFound; | ||||
| 
 | ||||
|     //add a marker so we can detect cyclic dependencies
 | ||||
|     // add a marker so we can detect cyclic dependencies
 | ||||
|     this.injector._markAsConstructing(key); | ||||
| 
 | ||||
|     var deps = this.injector._resolveDependencies(key, binding, true); | ||||
|     var depsPromise = PromiseWrapper.all(deps); | ||||
| 
 | ||||
|     var promise = PromiseWrapper | ||||
|       .then(depsPromise, null, (e) => this._errorHandler(key, e)) | ||||
|       .then(deps => this._findOrCreate(key, binding, deps)) | ||||
|       .then(instance => this._cacheInstance(key, instance)); | ||||
|     var promise = PromiseWrapper.then(depsPromise, null, (e) => this._errorHandler(key, e)) | ||||
|                       .then(deps => this._findOrCreate(key, binding, deps)) | ||||
|                       .then(instance => this._cacheInstance(key, instance)); | ||||
| 
 | ||||
|     this.injector._setInstance(key, new _Waiting(promise)); | ||||
|     return promise; | ||||
|   } | ||||
| 
 | ||||
|   _errorHandler(key:Key, e):Promise { | ||||
|   _errorHandler(key: Key, e): Promise<any> { | ||||
|     if (e instanceof AbstractBindingError) e.addKey(key); | ||||
|     return PromiseWrapper.reject(e); | ||||
|   } | ||||
| 
 | ||||
|   _findOrCreate(key:Key, binding:ResolvedBinding, deps:List) { | ||||
|   _findOrCreate(key: Key, binding: ResolvedBinding, deps: List<any>) { | ||||
|     try { | ||||
|       var instance = this.injector._getInstance(key); | ||||
|       if (!_isWaiting(instance)) return instance; | ||||
| @ -365,7 +362,7 @@ class _AsyncInjectorStrategy { | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| function _resolveBindings(bindings:List): List { | ||||
| function _resolveBindings(bindings: List<any>): List<ResolvedBinding> { | ||||
|   var resolvedList = ListWrapper.createFixedSize(bindings.length); | ||||
|   for (var i = 0; i < bindings.length; i++) { | ||||
|     var unresolved = bindings[i]; | ||||
| @ -379,7 +376,7 @@ function _resolveBindings(bindings:List): List { | ||||
|     } else if (unresolved instanceof List) { | ||||
|       resolved = _resolveBindings(unresolved); | ||||
|     } else if (unresolved instanceof BindingBuilder) { | ||||
|       throw new InvalidBindingError('BindingBuilder with ' + unresolved.token + ' token'); | ||||
|       throw new InvalidBindingError(unresolved.token); | ||||
|     } else { | ||||
|       throw new InvalidBindingError(unresolved); | ||||
|     } | ||||
| @ -388,14 +385,15 @@ function _resolveBindings(bindings:List): List { | ||||
|   return resolvedList; | ||||
| } | ||||
| 
 | ||||
| function _createListOfBindings(flattenedBindings):List { | ||||
| function _createListOfBindings(flattenedBindings): List<any> { | ||||
|   var bindings = ListWrapper.createFixedSize(Key.numberOfKeys + 1); | ||||
|   MapWrapper.forEach(flattenedBindings, (v, keyId) => bindings[keyId] = v); | ||||
|   return bindings; | ||||
| } | ||||
| 
 | ||||
| function _flattenBindings(bindings:List, res:Map):Map { | ||||
|   ListWrapper.forEach(bindings, function (b) { | ||||
| function _flattenBindings(bindings: List<ResolvedBinding /* | List<any>*/>, | ||||
|                           res: Map<number, ResolvedBinding>): Map<number, ResolvedBinding> { | ||||
|   ListWrapper.forEach(bindings, function(b) { | ||||
|     if (b instanceof ResolvedBinding) { | ||||
|       MapWrapper.set(res, b.key.id, b); | ||||
|     } else if (b instanceof List) { | ||||
| @ -16,42 +16,34 @@ import {stringify} from 'angular2/src/facade/lang'; | ||||
|  * @exportedAs angular2/di | ||||
|  */ | ||||
| export class Key { | ||||
|   token; | ||||
|   id/* :int */; | ||||
|   constructor(token, id/* :int */) { | ||||
|   token: Object; | ||||
|   id: number; | ||||
|   constructor(token: Object, id: number) { | ||||
|     this.token = token; | ||||
|     this.id = id; | ||||
|   } | ||||
| 
 | ||||
|   get displayName() { | ||||
|     return stringify(this.token); | ||||
|   } | ||||
|   get displayName() { return stringify(this.token); } | ||||
| 
 | ||||
|   /** | ||||
|    * Retrieves a `Key` for a token. | ||||
|    */ | ||||
|   static get(token):Key { | ||||
|     return _globalKeyRegistry.get(token); | ||||
|   } | ||||
|   static get(token): Key { return _globalKeyRegistry.get(token); } | ||||
| 
 | ||||
|   /** | ||||
|    * @returns the number of keys registered in the system. | ||||
|    */ | ||||
|   static get numberOfKeys()/* :int */ { | ||||
|     return _globalKeyRegistry.numberOfKeys; | ||||
|   } | ||||
|   static get numberOfKeys(): number { return _globalKeyRegistry.numberOfKeys; } | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * @private | ||||
|  */ | ||||
| export class KeyRegistry { | ||||
|   _allKeys:Map; | ||||
|   constructor() { | ||||
|     this._allKeys = MapWrapper.create(); | ||||
|   } | ||||
|   _allKeys: Map<Object, Key>; | ||||
|   constructor() { this._allKeys = MapWrapper.create(); } | ||||
| 
 | ||||
|   get(token):Key { | ||||
|   get(token: Object): Key { | ||||
|     if (token instanceof Key) return token; | ||||
| 
 | ||||
|     if (MapWrapper.contains(this._allKeys, token)) { | ||||
| @ -63,9 +55,7 @@ export class KeyRegistry { | ||||
|     return newKey; | ||||
|   } | ||||
| 
 | ||||
|   get numberOfKeys()/* :int */ { | ||||
|     return MapWrapper.size(this._allKeys); | ||||
|   } | ||||
|   get numberOfKeys() /* :int */ { return MapWrapper.size(this._allKeys); } | ||||
| } | ||||
| 
 | ||||
| var _globalKeyRegistry = new KeyRegistry(); | ||||
							
								
								
									
										16
									
								
								modules/angular2/src/di/opaque_token.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										16
									
								
								modules/angular2/src/di/opaque_token.js
									
									
									
									
										vendored
									
									
								
							| @ -1,16 +0,0 @@ | ||||
| /** | ||||
|  *  | ||||
|  *  | ||||
|  * @exportedAs angular2/di | ||||
|  */ | ||||
| export class OpaqueToken { | ||||
|   _desc:string; | ||||
| 
 | ||||
|   constructor(desc:string){ | ||||
|     this._desc = `Token(${desc})`; | ||||
|   } | ||||
| 
 | ||||
|   toString():string { | ||||
|     return this._desc; | ||||
|   } | ||||
| } | ||||
							
								
								
									
										12
									
								
								modules/angular2/src/di/opaque_token.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								modules/angular2/src/di/opaque_token.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | ||||
| /** | ||||
|  * | ||||
|  * | ||||
|  * @exportedAs angular2/di | ||||
|  */ | ||||
| export class OpaqueToken { | ||||
|   _desc: string; | ||||
| 
 | ||||
|   constructor(desc: string) { this._desc = `Token(${desc})`; } | ||||
| 
 | ||||
|   toString(): string { return this._desc; } | ||||
| } | ||||
| @ -10,6 +10,8 @@ import {int, global, isPresent} from 'angular2/src/facade/lang'; | ||||
| import {List} from 'angular2/src/facade/collection'; | ||||
| import * as Rx from 'rx'; | ||||
| 
 | ||||
| export var Promise = (<any>global).Promise; | ||||
| 
 | ||||
| export class PromiseWrapper { | ||||
|   static resolve(obj): Promise<any> { return Promise.resolve(obj); } | ||||
| 
 | ||||
|  | ||||
| @ -161,7 +161,7 @@ class FunctionWrapper { | ||||
| class BaseException extends Error { | ||||
|   final String message; | ||||
| 
 | ||||
|   BaseException(this.message); | ||||
|   BaseException([this.message]); | ||||
| 
 | ||||
|   String toString() { | ||||
|     return this.message; | ||||
|  | ||||
| @ -9,6 +9,18 @@ export var __esModule = true; | ||||
| export var Type = Function; | ||||
| export type Type = typeof Function; | ||||
| 
 | ||||
| export class BaseException extends Error { | ||||
|   message; | ||||
|   stack; | ||||
|   constructor(message?: string) { | ||||
|     super(message); | ||||
|     this.message = message; | ||||
|     this.stack = (<any>new Error()).stack; | ||||
|   } | ||||
| 
 | ||||
|   toString(): string { return this.message; } | ||||
| } | ||||
| 
 | ||||
| export var Math = _global.Math; | ||||
| export var Date = _global.Date; | ||||
| 
 | ||||
| @ -28,7 +40,9 @@ if (assertionsEnabled_) { | ||||
| } | ||||
| export {int}; | ||||
| 
 | ||||
| export class CONST {} | ||||
| export function CONST() { | ||||
|   return (target) => target; | ||||
| }; | ||||
| export class ABSTRACT {} | ||||
| export class IMPLEMENTS {} | ||||
| 
 | ||||
| @ -111,10 +125,10 @@ export class StringJoiner { | ||||
|   toString(): string { return this.parts.join(""); } | ||||
| } | ||||
| 
 | ||||
| export class NumberParseError implements Error { | ||||
| export class NumberParseError extends BaseException { | ||||
|   name: string; | ||||
| 
 | ||||
|   constructor(public message: string) {} | ||||
|   constructor(public message: string) { super(); } | ||||
| 
 | ||||
|   toString() { return this.message; } | ||||
| } | ||||
| @ -191,9 +205,6 @@ export class FunctionWrapper { | ||||
|   static apply(fn: Function, posArgs) { return fn.apply(null, posArgs); } | ||||
| } | ||||
| 
 | ||||
| // No subclass so that we preserve error stack.
 | ||||
| export var BaseException = Error; | ||||
| 
 | ||||
| // JS has NaN !== NaN
 | ||||
| export function looseIdentical(a, b): boolean { | ||||
|   return a === b || typeof a === "number" && typeof b === "number" && isNaN(a) && isNaN(b); | ||||
|  | ||||
							
								
								
									
										1
									
								
								modules/angular2/src/util/decorators.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								modules/angular2/src/util/decorators.dart
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | ||||
| library util_decorators; | ||||
| @ -1,12 +1,16 @@ | ||||
| export var __esModule = true; | ||||
| 
 | ||||
| import {global} from 'angular2/src/facade/lang'; | ||||
| 
 | ||||
| export function makeDecorator(annotationCls) { | ||||
|   return function(...args) { | ||||
|   return function() { | ||||
|     var args = arguments; | ||||
|     var Reflect = global.Reflect; | ||||
|     if (!(Reflect && Reflect.getMetadata)) { | ||||
|       throw 'reflect-metadata shim is required when using class decorators'; | ||||
|     } | ||||
|     var annotationInstance = new annotationCls(...args); | ||||
|     var annotationInstance = Object.create(annotationCls); | ||||
|     annotationInstance.call(annotationInstance, args); | ||||
|     return function(cls) { | ||||
|       var annotations = Reflect.getMetadata('annotations', cls); | ||||
|       annotations = annotations || []; | ||||
| @ -18,12 +22,14 @@ export function makeDecorator(annotationCls) { | ||||
| } | ||||
| 
 | ||||
| export function makeParamDecorator(annotationCls) { | ||||
|   return function(...args) { | ||||
|   return function() { | ||||
|     var args = arguments; | ||||
|     var Reflect = global.Reflect; | ||||
|     if (!(Reflect && Reflect.getMetadata)) { | ||||
|       throw 'reflect-metadata shim is required when using parameter decorators'; | ||||
|     } | ||||
|     var annotationInstance = new annotationCls(...args); | ||||
|     var annotationInstance = Object.create(annotationCls); | ||||
|     annotationInstance.call(annotationInstance, args); | ||||
|     return function(cls, unusedKey, index) { | ||||
|       var parameters = Reflect.getMetadata('parameters', cls); | ||||
|       parameters = parameters || []; | ||||
							
								
								
									
										3
									
								
								modules/angular2/test/di/injector_spec.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								modules/angular2/test/di/injector_spec.js
									
									
									
									
										vendored
									
									
								
							| @ -77,6 +77,7 @@ class NoAnnotations { | ||||
| 
 | ||||
| export function main() { | ||||
|   describe('injector', function () { | ||||
| 
 | ||||
|     it('should instantiate a class without dependencies', function () { | ||||
|       var injector = Injector.resolveAndCreate([Engine]); | ||||
|       var engine = injector.get(Engine); | ||||
| @ -211,7 +212,7 @@ export function main() { | ||||
|         .toThrowError('Invalid binding - only instances of Binding and Type are allowed, got: blah'); | ||||
|       expect(() => Injector.resolveAndCreate([bind("blah")])) | ||||
|         .toThrowError('Invalid binding - only instances of Binding and Type are allowed, ' + | ||||
|         'got: BindingBuilder with blah token'); | ||||
|         'got: blah'); | ||||
|     }); | ||||
| 
 | ||||
|     it('should provide itself', function () { | ||||
|  | ||||
| @ -22,6 +22,7 @@ class SpyTestObj extends SpyObject { | ||||
|   noSuchMethod(m){return super.noSuchMethod(m)} | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| export function main() { | ||||
|   describe('test_lib', () => { | ||||
|     describe('equality', () => { | ||||
|  | ||||
| @ -9509,7 +9509,7 @@ | ||||
|     }, | ||||
|     "typescript": { | ||||
|       "version": "1.5.0-beta", | ||||
|       "resolved": "git://github.com/alexeagle/TypeScript#cddc1867c44b6bed9095dc30f0b0f552cbc003a9" | ||||
|       "resolved": "git://github.com/alexeagle/TypeScript#be9a7edff73ac2592e508732c771c85357041385" | ||||
|     }, | ||||
|     "vinyl": { | ||||
|       "version": "0.4.6", | ||||
|  | ||||
							
								
								
									
										2
									
								
								npm-shrinkwrap.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								npm-shrinkwrap.json
									
									
									
										generated
									
									
									
								
							| @ -14695,7 +14695,7 @@ | ||||
|     "typescript": { | ||||
|       "version": "1.5.0-beta", | ||||
|       "from": "git://github.com/alexeagle/TypeScript#error_is_class", | ||||
|       "resolved": "git://github.com/alexeagle/TypeScript#cddc1867c44b6bed9095dc30f0b0f552cbc003a9" | ||||
|       "resolved": "git://github.com/alexeagle/TypeScript#be9a7edff73ac2592e508732c771c85357041385" | ||||
|     }, | ||||
|     "vinyl": { | ||||
|       "version": "0.4.6", | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user