2015-07-24 15:36:27 -07:00

823 lines
27 KiB
TypeScript

/// <reference path="../../typings/es6-promise/es6-promise.d.ts" />
import {Map, List, MapWrapper, ListWrapper} from 'angular2/src/facade/collection';
import {ResolvedBinding, Binding, Dependency, BindingBuilder, bind} from './binding';
import {
AbstractBindingError,
NoBindingError,
CyclicDependencyError,
InstantiationError,
InvalidBindingError,
OutOfBoundsError
} from './exceptions';
import {FunctionWrapper, Type, isPresent, isBlank, CONST_EXPR} from 'angular2/src/facade/lang';
import {Key} from './key';
import {resolveForwardRef} from './forward_ref';
import {VisibilityMetadata, DEFAULT_VISIBILITY, SelfMetadata, AncestorMetadata} from './metadata';
const _constructing = CONST_EXPR(new Object());
const _notFound = CONST_EXPR(new Object());
// Threshold for the dynamic version
const _MAX_CONSTRUCTION_COUNTER = 10;
export const undefinedValue: Object = CONST_EXPR(new Object());
export const PUBLIC: number = 1;
export const PRIVATE: number = 2;
export const PUBLIC_AND_PRIVATE: number = 3;
export interface ProtoInjectorStrategy {
getBindingAtIndex(index: number): ResolvedBinding;
createInjectorStrategy(inj: Injector): InjectorStrategy;
}
export class ProtoInjectorInlineStrategy implements ProtoInjectorStrategy {
binding0: ResolvedBinding = null;
binding1: ResolvedBinding = null;
binding2: ResolvedBinding = null;
binding3: ResolvedBinding = null;
binding4: ResolvedBinding = null;
binding5: ResolvedBinding = null;
binding6: ResolvedBinding = null;
binding7: ResolvedBinding = null;
binding8: ResolvedBinding = null;
binding9: ResolvedBinding = null;
keyId0: number = null;
keyId1: number = null;
keyId2: number = null;
keyId3: number = null;
keyId4: number = null;
keyId5: number = null;
keyId6: number = null;
keyId7: number = null;
keyId8: number = null;
keyId9: number = null;
visibility0: number = null;
visibility1: number = null;
visibility2: number = null;
visibility3: number = null;
visibility4: number = null;
visibility5: number = null;
visibility6: number = null;
visibility7: number = null;
visibility8: number = null;
visibility9: number = null;
constructor(protoEI: ProtoInjector, bwv: BindingWithVisibility[]) {
var length = bwv.length;
if (length > 0) {
this.binding0 = bwv[0].binding;
this.keyId0 = bwv[0].getKeyId();
this.visibility0 = bwv[0].visibility;
}
if (length > 1) {
this.binding1 = bwv[1].binding;
this.keyId1 = bwv[1].getKeyId();
this.visibility1 = bwv[1].visibility;
}
if (length > 2) {
this.binding2 = bwv[2].binding;
this.keyId2 = bwv[2].getKeyId();
this.visibility2 = bwv[2].visibility;
}
if (length > 3) {
this.binding3 = bwv[3].binding;
this.keyId3 = bwv[3].getKeyId();
this.visibility3 = bwv[3].visibility;
}
if (length > 4) {
this.binding4 = bwv[4].binding;
this.keyId4 = bwv[4].getKeyId();
this.visibility4 = bwv[4].visibility;
}
if (length > 5) {
this.binding5 = bwv[5].binding;
this.keyId5 = bwv[5].getKeyId();
this.visibility5 = bwv[5].visibility;
}
if (length > 6) {
this.binding6 = bwv[6].binding;
this.keyId6 = bwv[6].getKeyId();
this.visibility6 = bwv[6].visibility;
}
if (length > 7) {
this.binding7 = bwv[7].binding;
this.keyId7 = bwv[7].getKeyId();
this.visibility7 = bwv[7].visibility;
}
if (length > 8) {
this.binding8 = bwv[8].binding;
this.keyId8 = bwv[8].getKeyId();
this.visibility8 = bwv[8].visibility;
}
if (length > 9) {
this.binding9 = bwv[9].binding;
this.keyId9 = bwv[9].getKeyId();
this.visibility9 = bwv[9].visibility;
}
}
getBindingAtIndex(index: number): any {
if (index == 0) return this.binding0;
if (index == 1) return this.binding1;
if (index == 2) return this.binding2;
if (index == 3) return this.binding3;
if (index == 4) return this.binding4;
if (index == 5) return this.binding5;
if (index == 6) return this.binding6;
if (index == 7) return this.binding7;
if (index == 8) return this.binding8;
if (index == 9) return this.binding9;
throw new OutOfBoundsError(index);
}
createInjectorStrategy(injector: Injector): InjectorStrategy {
return new InjectorInlineStrategy(injector, this);
}
}
export class ProtoInjectorDynamicStrategy implements ProtoInjectorStrategy {
bindings: ResolvedBinding[];
keyIds: number[];
visibilities: number[];
constructor(protoInj: ProtoInjector, bwv: BindingWithVisibility[]) {
var len = bwv.length;
this.bindings = ListWrapper.createFixedSize(len);
this.keyIds = ListWrapper.createFixedSize(len);
this.visibilities = ListWrapper.createFixedSize(len);
for (var i = 0; i < len; i++) {
this.bindings[i] = bwv[i].binding;
this.keyIds[i] = bwv[i].getKeyId();
this.visibilities[i] = bwv[i].visibility;
}
}
getBindingAtIndex(index: number): any {
if (index < 0 || index >= this.bindings.length) {
throw new OutOfBoundsError(index);
}
return this.bindings[index];
}
createInjectorStrategy(ei: Injector): InjectorStrategy {
return new InjectorDynamicStrategy(this, ei);
}
}
export class ProtoInjector {
_strategy: ProtoInjectorStrategy;
numberOfBindings: number;
constructor(bwv: BindingWithVisibility[]) {
this.numberOfBindings = bwv.length;
this._strategy = bwv.length > _MAX_CONSTRUCTION_COUNTER ?
new ProtoInjectorDynamicStrategy(this, bwv) :
new ProtoInjectorInlineStrategy(this, bwv);
}
getBindingAtIndex(index: number): any { return this._strategy.getBindingAtIndex(index); }
}
export interface InjectorStrategy {
getObjByKeyId(keyId: number, visibility: number): any;
getObjAtIndex(index: number): any;
getMaxNumberOfObjects(): number;
attach(parent: Injector, isBoundary: boolean): void;
resetConstructionCounter(): void;
instantiateBinding(binding: ResolvedBinding, visibility: number): any;
}
export class InjectorInlineStrategy implements InjectorStrategy {
obj0: any = undefinedValue;
obj1: any = undefinedValue;
obj2: any = undefinedValue;
obj3: any = undefinedValue;
obj4: any = undefinedValue;
obj5: any = undefinedValue;
obj6: any = undefinedValue;
obj7: any = undefinedValue;
obj8: any = undefinedValue;
obj9: any = undefinedValue;
constructor(public injector: Injector, public protoStrategy: ProtoInjectorInlineStrategy) {}
resetConstructionCounter(): void { this.injector._constructionCounter = 0; }
instantiateBinding(binding: ResolvedBinding, visibility: number): any {
return this.injector._new(binding, visibility);
}
attach(parent: Injector, isBoundary: boolean): void {
var inj = this.injector;
inj._parent = parent;
inj._isBoundary = isBoundary;
}
getObjByKeyId(keyId: number, visibility: number): any {
var p = this.protoStrategy;
var inj = this.injector;
if (p.keyId0 === keyId && (p.visibility0 & visibility) > 0) {
if (this.obj0 === undefinedValue) {
this.obj0 = inj._new(p.binding0, p.visibility0);
}
return this.obj0;
}
if (p.keyId1 === keyId && (p.visibility1 & visibility) > 0) {
if (this.obj1 === undefinedValue) {
this.obj1 = inj._new(p.binding1, p.visibility1);
}
return this.obj1;
}
if (p.keyId2 === keyId && (p.visibility2 & visibility) > 0) {
if (this.obj2 === undefinedValue) {
this.obj2 = inj._new(p.binding2, p.visibility2);
}
return this.obj2;
}
if (p.keyId3 === keyId && (p.visibility3 & visibility) > 0) {
if (this.obj3 === undefinedValue) {
this.obj3 = inj._new(p.binding3, p.visibility3);
}
return this.obj3;
}
if (p.keyId4 === keyId && (p.visibility4 & visibility) > 0) {
if (this.obj4 === undefinedValue) {
this.obj4 = inj._new(p.binding4, p.visibility4);
}
return this.obj4;
}
if (p.keyId5 === keyId && (p.visibility5 & visibility) > 0) {
if (this.obj5 === undefinedValue) {
this.obj5 = inj._new(p.binding5, p.visibility5);
}
return this.obj5;
}
if (p.keyId6 === keyId && (p.visibility6 & visibility) > 0) {
if (this.obj6 === undefinedValue) {
this.obj6 = inj._new(p.binding6, p.visibility6);
}
return this.obj6;
}
if (p.keyId7 === keyId && (p.visibility7 & visibility) > 0) {
if (this.obj7 === undefinedValue) {
this.obj7 = inj._new(p.binding7, p.visibility7);
}
return this.obj7;
}
if (p.keyId8 === keyId && (p.visibility8 & visibility) > 0) {
if (this.obj8 === undefinedValue) {
this.obj8 = inj._new(p.binding8, p.visibility8);
}
return this.obj8;
}
if (p.keyId9 === keyId && (p.visibility9 & visibility) > 0) {
if (this.obj9 === undefinedValue) {
this.obj9 = inj._new(p.binding9, p.visibility9);
}
return this.obj9;
}
return undefinedValue;
}
getObjAtIndex(index: number): any {
if (index == 0) return this.obj0;
if (index == 1) return this.obj1;
if (index == 2) return this.obj2;
if (index == 3) return this.obj3;
if (index == 4) return this.obj4;
if (index == 5) return this.obj5;
if (index == 6) return this.obj6;
if (index == 7) return this.obj7;
if (index == 8) return this.obj8;
if (index == 9) return this.obj9;
throw new OutOfBoundsError(index);
}
getMaxNumberOfObjects(): number { return _MAX_CONSTRUCTION_COUNTER; }
}
export class InjectorDynamicStrategy implements InjectorStrategy {
objs: any[];
constructor(public protoStrategy: ProtoInjectorDynamicStrategy, public injector: Injector) {
this.objs = ListWrapper.createFixedSize(protoStrategy.bindings.length);
ListWrapper.fill(this.objs, undefinedValue);
}
resetConstructionCounter(): void { this.injector._constructionCounter = 0; }
instantiateBinding(binding: ResolvedBinding, visibility: number): any {
return this.injector._new(binding, visibility);
}
attach(parent: Injector, isBoundary: boolean): void {
var inj = this.injector;
inj._parent = parent;
inj._isBoundary = isBoundary;
}
getObjByKeyId(keyId: number, visibility: number): any {
var p = this.protoStrategy;
for (var i = 0; i < p.keyIds.length; i++) {
if (p.keyIds[i] === keyId && (p.visibilities[i] & visibility) > 0) {
if (this.objs[i] === undefinedValue) {
this.objs[i] = this.injector._new(p.bindings[i], p.visibilities[i]);
}
return this.objs[i];
}
}
return undefinedValue;
}
getObjAtIndex(index: number): any {
if (index < 0 || index >= this.objs.length) {
throw new OutOfBoundsError(index);
}
return this.objs[index];
}
getMaxNumberOfObjects(): number { return this.objs.length; }
}
export class BindingWithVisibility {
constructor(public binding: ResolvedBinding, public visibility: number){};
getKeyId(): number { return this.binding.key.id; }
}
/**
* Used to provide dependencies that cannot be easily expressed as bindings.
*/
export interface DependencyProvider {
getDependency(injector: Injector, binding: ResolvedBinding, dependency: Dependency): any;
}
/**
* 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`.
*
* ## Example:
*
* Suppose that we want to inject an `Engine` into class `Car`, we would define it like this:
*
* ```javascript
* class Engine {
* }
*
* class Car {
* 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.
*
* ```javascript
* main() {
* var injector = Injector.resolveAndCreate([Car, Engine]);
*
* // Get a reference to the `root` object, which will recursively instantiate the tree.
* 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.
*/
export class Injector {
/**
* 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.
*
* @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
* `fromResolvedBindings` and `createChildFromResolved`.
*/
static resolve(bindings: List<Type | Binding | List<any>>): List<ResolvedBinding> {
var resolvedBindings = _resolveBindings(bindings);
var flatten = _flattenBindings(resolvedBindings, new Map());
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}.
*
* 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
* bindings.
* @param `depProvider`
*/
static resolveAndCreate(bindings: List<Type | Binding | List<any>>,
depProvider: DependencyProvider = null): Injector {
var resolvedBindings = Injector.resolve(bindings);
return Injector.fromResolvedBindings(resolvedBindings, depProvider);
}
/**
* 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 `depProvider`
*/
static fromResolvedBindings(bindings: List<ResolvedBinding>,
depProvider: DependencyProvider = null): Injector {
var bd = bindings.map(b => new BindingWithVisibility(b, PUBLIC));
var proto = new ProtoInjector(bd);
var inj = new Injector(proto, null, depProvider);
return inj;
}
_strategy: InjectorStrategy;
_isBoundary: boolean = false;
_constructionCounter: number = 0;
constructor(public _proto: ProtoInjector, public _parent: Injector = null,
private _depProvider: DependencyProvider = null,
private _debugContext: Function = null) {
this._strategy = _proto._strategy.createInjectorStrategy(this);
}
/**
* Returns debug information about the injector.
*
* This information is included into exceptions thrown by the injector.
*/
debugContext(): any { return this._debugContext(); }
/**
* Retrieves an instance from the injector.
*
* @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: any): any {
return this._getByKey(Key.get(token), DEFAULT_VISIBILITY, false, PUBLIC_AND_PRIVATE);
}
/**
* Retrieves an instance from the 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: any): any {
return this._getByKey(Key.get(token), DEFAULT_VISIBILITY, true, PUBLIC_AND_PRIVATE);
}
/**
* Retrieves an instance from the injector.
*
* @param `index`: index of an instance.
* @returns an instance represented by the index. Throws if not found.
*/
getAt(index: number): any { return this._strategy.getObjAtIndex(index); }
/**
* Direct parent of this injector.
*/
get parent(): Injector { return this._parent; }
/**
* Internal. Do not use.
*
* We return `any` not to export the InjectorStrategy type.
*/
get internalStrategy(): any { return this._strategy; }
/**
* 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.
*
* @param `bindings` can be a list of `Type`, {@link Binding}, {@link ResolvedBinding}, or a
* recursive list of more bindings.
* @param `depProvider`
*/
resolveAndCreateChild(bindings: List<Type | Binding | List<any>>,
depProvider: DependencyProvider = null): Injector {
var resovledBindings = Injector.resolve(bindings);
return this.createChildFromResolved(resovledBindings, depProvider);
}
/**
* 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 `depProvider`
* @returns a new child {@link Injector}.
*/
createChildFromResolved(bindings: List<ResolvedBinding>,
depProvider: DependencyProvider = null): Injector {
var bd = bindings.map(b => new BindingWithVisibility(b, PUBLIC));
var proto = new ProtoInjector(bd);
var inj = new Injector(proto, null, depProvider);
inj._parent = this;
return inj;
}
_new(binding: ResolvedBinding, visibility: number): any {
if (this._constructionCounter++ > this._strategy.getMaxNumberOfObjects()) {
throw new CyclicDependencyError(this, binding.key);
}
var factory = binding.factory;
var deps = binding.dependencies;
var length = deps.length;
var d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15, d16, d17, d18, d19;
try {
d0 = length > 0 ? this._getByDependency(binding, deps[0], visibility) : null;
d1 = length > 1 ? this._getByDependency(binding, deps[1], visibility) : null;
d2 = length > 2 ? this._getByDependency(binding, deps[2], visibility) : null;
d3 = length > 3 ? this._getByDependency(binding, deps[3], visibility) : null;
d4 = length > 4 ? this._getByDependency(binding, deps[4], visibility) : null;
d5 = length > 5 ? this._getByDependency(binding, deps[5], visibility) : null;
d6 = length > 6 ? this._getByDependency(binding, deps[6], visibility) : null;
d7 = length > 7 ? this._getByDependency(binding, deps[7], visibility) : null;
d8 = length > 8 ? this._getByDependency(binding, deps[8], visibility) : null;
d9 = length > 9 ? this._getByDependency(binding, deps[9], visibility) : null;
d10 = length > 10 ? this._getByDependency(binding, deps[10], visibility) : null;
d11 = length > 11 ? this._getByDependency(binding, deps[11], visibility) : null;
d12 = length > 12 ? this._getByDependency(binding, deps[12], visibility) : null;
d13 = length > 13 ? this._getByDependency(binding, deps[13], visibility) : null;
d14 = length > 14 ? this._getByDependency(binding, deps[14], visibility) : null;
d15 = length > 15 ? this._getByDependency(binding, deps[15], visibility) : null;
d16 = length > 16 ? this._getByDependency(binding, deps[16], visibility) : null;
d17 = length > 17 ? this._getByDependency(binding, deps[17], visibility) : null;
d18 = length > 18 ? this._getByDependency(binding, deps[18], visibility) : null;
d19 = length > 19 ? this._getByDependency(binding, deps[19], visibility) : null;
} catch (e) {
if (e instanceof AbstractBindingError) {
e.addKey(this, binding.key);
}
throw e;
}
var obj;
try {
switch (length) {
case 0:
obj = factory();
break;
case 1:
obj = factory(d0);
break;
case 2:
obj = factory(d0, d1);
break;
case 3:
obj = factory(d0, d1, d2);
break;
case 4:
obj = factory(d0, d1, d2, d3);
break;
case 5:
obj = factory(d0, d1, d2, d3, d4);
break;
case 6:
obj = factory(d0, d1, d2, d3, d4, d5);
break;
case 7:
obj = factory(d0, d1, d2, d3, d4, d5, d6);
break;
case 8:
obj = factory(d0, d1, d2, d3, d4, d5, d6, d7);
break;
case 9:
obj = factory(d0, d1, d2, d3, d4, d5, d6, d7, d8);
break;
case 10:
obj = factory(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9);
break;
case 11:
obj = factory(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10);
break;
case 12:
obj = factory(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11);
break;
case 13:
obj = factory(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12);
break;
case 14:
obj = factory(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13);
break;
case 15:
obj = factory(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14);
break;
case 16:
obj = factory(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15);
break;
case 17:
obj = factory(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15, d16);
break;
case 18:
obj = factory(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15, d16,
d17);
break;
case 19:
obj = factory(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15, d16,
d17, d18);
break;
case 20:
obj = factory(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15, d16,
d17, d18, d19);
break;
}
} catch (e) {
throw new InstantiationError(this, e, e.stack, binding.key);
}
return obj;
}
private _getByDependency(binding: ResolvedBinding, dep: Dependency,
bindingVisibility: number): any {
var special = isPresent(this._depProvider) ?
this._depProvider.getDependency(this, binding, dep) :
undefinedValue;
if (special !== undefinedValue) {
return special;
} else {
return this._getByKey(dep.key, dep.visibility, dep.optional, bindingVisibility);
}
}
private _getByKey(key: Key, depVisibility: VisibilityMetadata, optional: boolean,
bindingVisibility: number): any {
if (key === INJECTOR_KEY) {
return this;
}
if (depVisibility instanceof SelfMetadata) {
return this._getByKeySelf(key, optional, bindingVisibility);
} else if (depVisibility instanceof AncestorMetadata) {
return this._getByKeyAncestor(key, optional, bindingVisibility, depVisibility.includeSelf);
} else {
return this._getByKeyUnbounded(key, optional, bindingVisibility, depVisibility.includeSelf);
}
}
_throwOrNull(key: Key, optional: boolean): any {
if (optional) {
return null;
} else {
throw new NoBindingError(this, key);
}
}
_getByKeySelf(key: Key, optional: boolean, bindingVisibility: number): any {
var obj = this._strategy.getObjByKeyId(key.id, bindingVisibility);
return (obj !== undefinedValue) ? obj : this._throwOrNull(key, optional);
}
_getByKeyAncestor(key: Key, optional: boolean, bindingVisibility: number,
includeSelf: boolean): any {
var inj = this;
if (!includeSelf) {
if (inj._isBoundary) {
return this._getPrivateDependency(key, optional, inj);
} else {
inj = inj._parent;
}
}
while (inj != null) {
var obj = inj._strategy.getObjByKeyId(key.id, bindingVisibility);
if (obj !== undefinedValue) return obj;
if (isPresent(inj._parent) && inj._isBoundary) {
return this._getPrivateDependency(key, optional, inj);
} else {
inj = inj._parent;
}
}
return this._throwOrNull(key, optional);
}
_getPrivateDependency(key: Key, optional: boolean, inj: Injector): any {
var obj = inj._parent._strategy.getObjByKeyId(key.id, PRIVATE);
return (obj !== undefinedValue) ? obj : this._throwOrNull(key, optional);
}
_getByKeyUnbounded(key: Key, optional: boolean, bindingVisibility: number,
includeSelf: boolean): any {
var inj = this;
if (!includeSelf) {
bindingVisibility = inj._isBoundary ? PUBLIC_AND_PRIVATE : PUBLIC;
inj = inj._parent;
}
while (inj != null) {
var obj = inj._strategy.getObjByKeyId(key.id, bindingVisibility);
if (obj !== undefinedValue) return obj;
bindingVisibility = inj._isBoundary ? PUBLIC_AND_PRIVATE : PUBLIC;
inj = inj._parent;
}
return this._throwOrNull(key, optional);
}
get displayName(): string {
return `Injector(bindings: [${_mapBindings(this, b => ` "${b.key.displayName}" `).join(", ")}])`;
}
toString(): string { return this.displayName; }
}
var INJECTOR_KEY = Key.get(Injector);
function _resolveBindings(bindings: List<Type | Binding | List<any>>): List<ResolvedBinding> {
var resolvedList = ListWrapper.createFixedSize(bindings.length);
for (var i = 0; i < bindings.length; i++) {
var unresolved = resolveForwardRef(bindings[i]);
var resolved;
if (unresolved instanceof ResolvedBinding) {
resolved = unresolved; // ha-ha! I'm easily amused
} else if (unresolved instanceof Type) {
resolved = bind(unresolved).toClass(unresolved).resolve();
} else if (unresolved instanceof Binding) {
resolved = unresolved.resolve();
} else if (unresolved instanceof List) {
resolved = _resolveBindings(unresolved);
} else if (unresolved instanceof BindingBuilder) {
throw new InvalidBindingError(unresolved.token);
} else {
throw new InvalidBindingError(unresolved);
}
resolvedList[i] = resolved;
}
return resolvedList;
}
function _createListOfBindings(flattenedBindings: Map<number, ResolvedBinding>):
List<ResolvedBinding> {
return MapWrapper.values(flattenedBindings);
}
function _flattenBindings(bindings: List<ResolvedBinding | List<any>>,
res: Map<number, ResolvedBinding>): Map<number, ResolvedBinding> {
ListWrapper.forEach(bindings, function(b) {
if (b instanceof ResolvedBinding) {
res.set(b.key.id, b);
} else if (b instanceof List) {
_flattenBindings(b, res);
}
});
return res;
}
function _mapBindings(injector: Injector, fn: Function): any[] {
var res = [];
for (var i = 0; i < injector._proto.numberOfBindings; ++i) {
res.push(fn(injector._proto.getBindingAtIndex(i)));
}
return res;
}