fix(di): refactor bindings to support Dart annotations
This commit is contained in:
parent
ff6e7754ae
commit
6c8398df9b
|
@ -756,7 +756,6 @@ gulp.task('build/packages.dart', function(done) {
|
||||||
'build/transpile.dart', // Creates the folder structure needed by subsequent tasks.
|
'build/transpile.dart', // Creates the folder structure needed by subsequent tasks.
|
||||||
['build/html.dart', 'build/copy.dart', 'build/multicopy.dart'],
|
['build/html.dart', 'build/copy.dart', 'build/multicopy.dart'],
|
||||||
'build/format.dart',
|
'build/format.dart',
|
||||||
'build/pubspec.dart',
|
|
||||||
done
|
done
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -765,6 +764,7 @@ gulp.task('build/packages.dart', function(done) {
|
||||||
gulp.task('build.dart', function(done) {
|
gulp.task('build.dart', function(done) {
|
||||||
runSequence(
|
runSequence(
|
||||||
'build/packages.dart',
|
'build/packages.dart',
|
||||||
|
'build/pubspec.dart',
|
||||||
'build/analyze.dart',
|
'build/analyze.dart',
|
||||||
'build/pubbuild.dart',
|
'build/pubbuild.dart',
|
||||||
done
|
done
|
||||||
|
|
|
@ -13,6 +13,7 @@ module.exports = function(config) {
|
||||||
// Unit test files needs to be included.
|
// Unit test files needs to be included.
|
||||||
// Karma-dart generates `__adapter_unittest.dart` that imports these files.
|
// Karma-dart generates `__adapter_unittest.dart` that imports these files.
|
||||||
{pattern: 'modules/*/test/**/*_spec.js', included: true},
|
{pattern: 'modules/*/test/**/*_spec.js', included: true},
|
||||||
|
{pattern: 'modules/*/test/**/*_spec.dart', included: true},
|
||||||
{pattern: 'tools/transpiler/spec/**/*_spec.js', included: true},
|
{pattern: 'tools/transpiler/spec/**/*_spec.js', included: true},
|
||||||
|
|
||||||
// These files are not included, they are imported by the unit tests above.
|
// These files are not included, they are imported by the unit tests above.
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
export {Inject, InjectPromise, InjectLazy, Injectable, Optional, DependencyAnnotation} from './src/di/annotations';
|
export {Inject, InjectPromise, InjectLazy, Injectable, Optional, DependencyAnnotation} from './src/di/annotations';
|
||||||
export {Injector} from './src/di/injector';
|
export {Injector} from './src/di/injector';
|
||||||
export {Binding, Dependency, bind} from './src/di/binding';
|
export {Binding, ResolvedBinding, Dependency, bind} from './src/di/binding';
|
||||||
export {Key, KeyRegistry} from './src/di/key';
|
export {Key, KeyRegistry} from './src/di/key';
|
||||||
export {KeyMetadataError, NoProviderError, ProviderError, AsyncBindingError, CyclicDependencyError,
|
export {KeyMetadataError, NoProviderError, ProviderError, AsyncBindingError, CyclicDependencyError,
|
||||||
InstantiationError, InvalidBindingError, NoAnnotationError} from './src/di/exceptions';
|
InstantiationError, InvalidBindingError, NoAnnotationError} from './src/di/exceptions';
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import {isPresent, isBlank, Type, int, BaseException} from 'angular2/src/facade/lang';
|
import {isPresent, isBlank, Type, int, BaseException} from 'angular2/src/facade/lang';
|
||||||
import {Math} from 'angular2/src/facade/math';
|
import {Math} from 'angular2/src/facade/math';
|
||||||
import {List, ListWrapper, MapWrapper} from 'angular2/src/facade/collection';
|
import {List, ListWrapper, MapWrapper} from 'angular2/src/facade/collection';
|
||||||
import {Injector, Key, Dependency, bind, Binding, NoProviderError, ProviderError, CyclicDependencyError} from 'angular2/di';
|
import {Injector, Key, Dependency, bind, Binding, ResolvedBinding, NoProviderError, ProviderError, CyclicDependencyError} from 'angular2/di';
|
||||||
import {Parent, Ancestor} from 'angular2/src/core/annotations/visibility';
|
import {Parent, Ancestor} from 'angular2/src/core/annotations/visibility';
|
||||||
import {EventEmitter, PropertySetter, Attribute, Query} from 'angular2/src/core/annotations/di';
|
import {EventEmitter, PropertySetter, Attribute, Query} from 'angular2/src/core/annotations/di';
|
||||||
import * as viewModule from 'angular2/src/core/compiler/view';
|
import * as viewModule from 'angular2/src/core/compiler/view';
|
||||||
|
@ -278,7 +278,7 @@ export class DirectiveDependency extends Dependency {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DirectiveBinding extends Binding {
|
export class DirectiveBinding extends ResolvedBinding {
|
||||||
callOnDestroy:boolean;
|
callOnDestroy:boolean;
|
||||||
callOnChange:boolean;
|
callOnChange:boolean;
|
||||||
callOnAllChangesDone:boolean;
|
callOnAllChangesDone:boolean;
|
||||||
|
@ -292,13 +292,14 @@ export class DirectiveBinding extends Binding {
|
||||||
this.annotation = annotation;
|
this.annotation = annotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
static createFromBinding(b:Binding, annotation:Directive):Binding {
|
static createFromBinding(b:Binding, annotation:Directive):DirectiveBinding {
|
||||||
var deps = ListWrapper.map(b.dependencies, DirectiveDependency.createFrom);
|
var rb = b.resolve();
|
||||||
return new DirectiveBinding(b.key, b.factory, deps, b.providedAsPromise, annotation);
|
var deps = ListWrapper.map(rb.dependencies, DirectiveDependency.createFrom);
|
||||||
|
return new DirectiveBinding(rb.key, rb.factory, deps, rb.providedAsPromise, annotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
static createFromType(type:Type, annotation:Directive):Binding {
|
static createFromType(type:Type, annotation:Directive):DirectiveBinding {
|
||||||
var binding = bind(type).toClass(type);
|
var binding = new Binding(type, {toClass: type});
|
||||||
return DirectiveBinding.createFromBinding(binding, annotation);
|
return DirectiveBinding.createFromBinding(binding, annotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,16 +344,16 @@ ElementInjector:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export class ProtoElementInjector {
|
export class ProtoElementInjector {
|
||||||
_binding0:Binding;
|
_binding0:ResolvedBinding;
|
||||||
_binding1:Binding;
|
_binding1:ResolvedBinding;
|
||||||
_binding2:Binding;
|
_binding2:ResolvedBinding;
|
||||||
_binding3:Binding;
|
_binding3:ResolvedBinding;
|
||||||
_binding4:Binding;
|
_binding4:ResolvedBinding;
|
||||||
_binding5:Binding;
|
_binding5:ResolvedBinding;
|
||||||
_binding6:Binding;
|
_binding6:ResolvedBinding;
|
||||||
_binding7:Binding;
|
_binding7:ResolvedBinding;
|
||||||
_binding8:Binding;
|
_binding8:ResolvedBinding;
|
||||||
_binding9:Binding;
|
_binding9:ResolvedBinding;
|
||||||
_binding0IsComponent:boolean;
|
_binding0IsComponent:boolean;
|
||||||
_keyId0:int;
|
_keyId0:int;
|
||||||
_keyId1:int;
|
_keyId1:int;
|
||||||
|
@ -642,7 +643,7 @@ export class ElementInjector extends TreeNode {
|
||||||
this._dynamicallyCreatedComponentBinding.key.id;
|
this._dynamicallyCreatedComponentBinding.key.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
_new(binding:Binding) {
|
_new(binding:ResolvedBinding) {
|
||||||
if (this._constructionCounter++ > _MAX_DIRECTIVE_CONSTRUCTION_COUNTER) {
|
if (this._constructionCounter++ > _MAX_DIRECTIVE_CONSTRUCTION_COUNTER) {
|
||||||
throw new CyclicDependencyError(binding.key);
|
throw new CyclicDependencyError(binding.key);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import {Type, isBlank, isPresent} from 'angular2/src/facade/lang';
|
import {Type, isBlank, isPresent, CONST} from 'angular2/src/facade/lang';
|
||||||
import {List, MapWrapper, ListWrapper} from 'angular2/src/facade/collection';
|
import {List, MapWrapper, ListWrapper} from 'angular2/src/facade/collection';
|
||||||
import {reflector} from 'angular2/src/reflection/reflection';
|
import {reflector} from 'angular2/src/reflection/reflection';
|
||||||
import {Key} from './key';
|
import {Key} from './key';
|
||||||
import {Inject, InjectLazy, InjectPromise, Optional, DependencyAnnotation} from './annotations';
|
import {Inject, InjectLazy, InjectPromise, Optional, DependencyAnnotation} from './annotations';
|
||||||
import {NoAnnotationError} from './exceptions';
|
import {NoAnnotationError, InvalidBindingError} from './exceptions';
|
||||||
|
|
||||||
export class Dependency {
|
export class Dependency {
|
||||||
key:Key;
|
key:Key;
|
||||||
|
@ -11,6 +11,7 @@ export class Dependency {
|
||||||
lazy:boolean;
|
lazy:boolean;
|
||||||
optional:boolean;
|
optional:boolean;
|
||||||
properties:List;
|
properties:List;
|
||||||
|
|
||||||
constructor(key:Key, asPromise:boolean, lazy:boolean, optional:boolean, properties:List) {
|
constructor(key:Key, asPromise:boolean, lazy:boolean, optional:boolean, properties:List) {
|
||||||
this.key = key;
|
this.key = key;
|
||||||
this.asPromise = asPromise;
|
this.asPromise = asPromise;
|
||||||
|
@ -24,13 +25,100 @@ export class Dependency {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _EMPTY_LIST = []; // TODO: make const when supported
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Declaration of a dependency binding.
|
||||||
|
*/
|
||||||
export class Binding {
|
export class Binding {
|
||||||
|
token;
|
||||||
|
toClass:Type;
|
||||||
|
toValue;
|
||||||
|
toAlias;
|
||||||
|
toFactory:Function;
|
||||||
|
toAsyncFactory:Function;
|
||||||
|
dependencies:List;
|
||||||
|
|
||||||
|
@CONST()
|
||||||
|
constructor(
|
||||||
|
token,
|
||||||
|
{
|
||||||
|
toClass,
|
||||||
|
toValue,
|
||||||
|
toAlias,
|
||||||
|
toFactory,
|
||||||
|
toAsyncFactory,
|
||||||
|
deps
|
||||||
|
}) {
|
||||||
|
this.token = token;
|
||||||
|
this.toClass = toClass;
|
||||||
|
this.toValue = toValue;
|
||||||
|
this.toAlias = toAlias;
|
||||||
|
this.toFactory = toFactory;
|
||||||
|
this.toAsyncFactory = toAsyncFactory;
|
||||||
|
this.dependencies = deps;
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(): ResolvedBinding {
|
||||||
|
var factoryFn:Function;
|
||||||
|
var resolvedDeps;
|
||||||
|
var isAsync = false;
|
||||||
|
if (isPresent(this.toClass)) {
|
||||||
|
factoryFn = reflector.factory(this.toClass);
|
||||||
|
resolvedDeps = _dependenciesFor(this.toClass);
|
||||||
|
} else if (isPresent(this.toAlias)) {
|
||||||
|
factoryFn = (aliasInstance) => aliasInstance;
|
||||||
|
resolvedDeps = [Dependency.fromKey(Key.get(this.toAlias))];
|
||||||
|
} else if (isPresent(this.toFactory)) {
|
||||||
|
factoryFn = this.toFactory;
|
||||||
|
resolvedDeps = _constructDependencies(this.toFactory, this.dependencies);
|
||||||
|
} else if (isPresent(this.toAsyncFactory)) {
|
||||||
|
factoryFn = this.toAsyncFactory;
|
||||||
|
resolvedDeps = _constructDependencies(this.toAsyncFactory, this.dependencies);
|
||||||
|
isAsync = true;
|
||||||
|
} else {
|
||||||
|
factoryFn = () => this.toValue;
|
||||||
|
resolvedDeps = _EMPTY_LIST;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ResolvedBinding(
|
||||||
|
Key.get(this.token),
|
||||||
|
factoryFn,
|
||||||
|
resolvedDeps,
|
||||||
|
isAsync
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static resolveAll(bindings:List): List {
|
||||||
|
var resolvedList = ListWrapper.createFixedSize(bindings.length);
|
||||||
|
for (var i = 0; i < bindings.length; i++) {
|
||||||
|
var unresolved = bindings[i];
|
||||||
|
var resolved;
|
||||||
|
if (unresolved instanceof Type) {
|
||||||
|
resolved = bind(unresolved).toClass(unresolved).resolve();
|
||||||
|
} else if (unresolved instanceof Binding) {
|
||||||
|
resolved = unresolved.resolve();
|
||||||
|
} else if (unresolved instanceof List) {
|
||||||
|
resolved = Binding.resolveAll(unresolved);
|
||||||
|
} else if (unresolved instanceof BindingBuilder) {
|
||||||
|
throw new InvalidBindingError(unresolved.token);
|
||||||
|
} else {
|
||||||
|
throw new InvalidBindingError(unresolved);
|
||||||
|
}
|
||||||
|
resolvedList[i] = resolved;
|
||||||
|
}
|
||||||
|
return resolvedList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Dependency binding with resolved keys and dependencies.
|
||||||
|
export class ResolvedBinding {
|
||||||
key:Key;
|
key:Key;
|
||||||
factory:Function;
|
factory:Function;
|
||||||
dependencies:List;
|
dependencies:List<Dependency>;
|
||||||
providedAsPromise:boolean;
|
providedAsPromise:boolean;
|
||||||
|
|
||||||
constructor(key:Key, factory:Function, dependencies:List, providedAsPromise:boolean) {
|
constructor(key:Key, factory:Function, dependencies:List<Dependency>, providedAsPromise:boolean) {
|
||||||
this.key = key;
|
this.key = key;
|
||||||
this.factory = factory;
|
this.factory = factory;
|
||||||
this.dependencies = dependencies;
|
this.dependencies = dependencies;
|
||||||
|
@ -38,66 +126,54 @@ export class Binding {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides fluent API for imperative construction of [Binding] objects.
|
||||||
|
*/
|
||||||
export function bind(token):BindingBuilder {
|
export function bind(token):BindingBuilder {
|
||||||
return new BindingBuilder(token);
|
return new BindingBuilder(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper class for [bind] function.
|
||||||
|
*/
|
||||||
export class BindingBuilder {
|
export class BindingBuilder {
|
||||||
token;
|
token;
|
||||||
|
|
||||||
constructor(token) {
|
constructor(token) {
|
||||||
this.token = token;
|
this.token = token;
|
||||||
}
|
}
|
||||||
|
|
||||||
toClass(type:Type):Binding {
|
toClass(type:Type):Binding {
|
||||||
return new Binding(
|
return new Binding(this.token, {toClass: type});
|
||||||
Key.get(this.token),
|
|
||||||
reflector.factory(type),
|
|
||||||
_dependenciesFor(type),
|
|
||||||
false
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
toValue(value):Binding {
|
toValue(value):Binding {
|
||||||
return new Binding(
|
return new Binding(this.token, {toValue: value});
|
||||||
Key.get(this.token),
|
|
||||||
() => value,
|
|
||||||
[],
|
|
||||||
false
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
toAlias(aliasToken):Binding {
|
toAlias(aliasToken):Binding {
|
||||||
return new Binding(
|
return new Binding(this.token, {toAlias: aliasToken});
|
||||||
Key.get(this.token),
|
|
||||||
(aliasInstance) => aliasInstance,
|
|
||||||
[Dependency.fromKey(Key.get(aliasToken))],
|
|
||||||
false
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
toFactory(factoryFunction:Function, dependencies:List = null):Binding {
|
toFactory(factoryFunction:Function, dependencies:List = null):Binding {
|
||||||
return new Binding(
|
return new Binding(this.token, {
|
||||||
Key.get(this.token),
|
toFactory: factoryFunction,
|
||||||
factoryFunction,
|
deps: dependencies
|
||||||
this._constructDependencies(factoryFunction, dependencies),
|
});
|
||||||
false
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
toAsyncFactory(factoryFunction:Function, dependencies:List = null):Binding {
|
toAsyncFactory(factoryFunction:Function, dependencies:List = null):Binding {
|
||||||
return new Binding(
|
return new Binding(this.token, {
|
||||||
Key.get(this.token),
|
toAsyncFactory: factoryFunction,
|
||||||
factoryFunction,
|
deps: dependencies
|
||||||
this._constructDependencies(factoryFunction, dependencies),
|
});
|
||||||
true
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_constructDependencies(factoryFunction:Function, dependencies:List) {
|
function _constructDependencies(factoryFunction:Function, dependencies:List) {
|
||||||
return isBlank(dependencies) ?
|
return isBlank(dependencies) ?
|
||||||
_dependenciesFor(factoryFunction) :
|
_dependenciesFor(factoryFunction) :
|
||||||
ListWrapper.map(dependencies, (t) => Dependency.fromKey(Key.get(t)));
|
ListWrapper.map(dependencies, (t) => Dependency.fromKey(Key.get(t)));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function _dependenciesFor(typeOrFunc):List {
|
function _dependenciesFor(typeOrFunc):List {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import {Map, List, MapWrapper, ListWrapper} from 'angular2/src/facade/collection';
|
import {Map, List, MapWrapper, ListWrapper} from 'angular2/src/facade/collection';
|
||||||
import {Binding, BindingBuilder, bind} from './binding';
|
import {ResolvedBinding, Binding, BindingBuilder, bind} from './binding';
|
||||||
import {ProviderError, NoProviderError, InvalidBindingError,
|
import {ProviderError, NoProviderError,
|
||||||
AsyncBindingError, CyclicDependencyError, InstantiationError} from './exceptions';
|
AsyncBindingError, CyclicDependencyError, InstantiationError} from './exceptions';
|
||||||
import {FunctionWrapper, Type, isPresent, isBlank} from 'angular2/src/facade/lang';
|
import {FunctionWrapper, Type, isPresent, isBlank} from 'angular2/src/facade/lang';
|
||||||
import {Promise, PromiseWrapper} from 'angular2/src/facade/async';
|
import {Promise, PromiseWrapper} from 'angular2/src/facade/async';
|
||||||
|
@ -28,7 +28,7 @@ export class Injector {
|
||||||
_asyncStrategy: _AsyncInjectorStrategy;
|
_asyncStrategy: _AsyncInjectorStrategy;
|
||||||
_syncStrategy:_SyncInjectorStrategy;
|
_syncStrategy:_SyncInjectorStrategy;
|
||||||
constructor(bindings:List, {parent=null, defaultBindings=false}={}) {
|
constructor(bindings:List, {parent=null, defaultBindings=false}={}) {
|
||||||
var flatten = _flattenBindings(bindings, MapWrapper.create());
|
var flatten = _flattenBindings(Binding.resolveAll(bindings), MapWrapper.create());
|
||||||
this._bindings = this._createListOfBindings(flatten);
|
this._bindings = this._createListOfBindings(flatten);
|
||||||
this._instances = this._createInstances();
|
this._instances = this._createInstances();
|
||||||
this._parent = parent;
|
this._parent = parent;
|
||||||
|
@ -89,7 +89,7 @@ export class Injector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_resolveDependencies(key:Key, binding:Binding, forceAsync:boolean):List {
|
_resolveDependencies(key:Key, binding:ResolvedBinding, forceAsync:boolean):List {
|
||||||
try {
|
try {
|
||||||
var getDependency = d => this._getByKey(d.key, forceAsync || d.asPromise, d.lazy, d.optional);
|
var getDependency = d => this._getByKey(d.key, forceAsync || d.asPromise, d.lazy, d.optional);
|
||||||
return ListWrapper.map(binding.dependencies, getDependency);
|
return ListWrapper.map(binding.dependencies, getDependency);
|
||||||
|
@ -115,7 +115,7 @@ export class Injector {
|
||||||
ListWrapper.get(this._bindings, key.id);
|
ListWrapper.get(this._bindings, key.id);
|
||||||
|
|
||||||
if (isBlank(binding) && this._defaultBindings) {
|
if (isBlank(binding) && this._defaultBindings) {
|
||||||
return bind(key.token).toClass(key.token);
|
return bind(key.token).toClass(key.token).resolve();
|
||||||
} else {
|
} else {
|
||||||
return binding;
|
return binding;
|
||||||
}
|
}
|
||||||
|
@ -166,7 +166,7 @@ class _SyncInjectorStrategy {
|
||||||
return this._createInstance(key, binding, deps);
|
return this._createInstance(key, binding, deps);
|
||||||
}
|
}
|
||||||
|
|
||||||
_createInstance(key:Key, binding:Binding, deps:List) {
|
_createInstance(key:Key, binding:ResolvedBinding, deps:List) {
|
||||||
try {
|
try {
|
||||||
var instance = FunctionWrapper.apply(binding.factory, deps);
|
var instance = FunctionWrapper.apply(binding.factory, deps);
|
||||||
this.injector._setInstance(key, instance);
|
this.injector._setInstance(key, instance);
|
||||||
|
@ -227,7 +227,7 @@ class _AsyncInjectorStrategy {
|
||||||
return PromiseWrapper.reject(e);
|
return PromiseWrapper.reject(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
_findOrCreate(key:Key, binding:Binding, deps:List) {
|
_findOrCreate(key:Key, binding:ResolvedBinding, deps:List) {
|
||||||
try {
|
try {
|
||||||
var instance = this.injector._getInstance(key);
|
var instance = this.injector._getInstance(key);
|
||||||
if (!_isWaiting(instance)) return instance;
|
if (!_isWaiting(instance)) return instance;
|
||||||
|
@ -246,21 +246,10 @@ class _AsyncInjectorStrategy {
|
||||||
|
|
||||||
function _flattenBindings(bindings:List, res:Map) {
|
function _flattenBindings(bindings:List, res:Map) {
|
||||||
ListWrapper.forEach(bindings, function (b) {
|
ListWrapper.forEach(bindings, function (b) {
|
||||||
if (b instanceof Binding) {
|
if (b instanceof ResolvedBinding) {
|
||||||
MapWrapper.set(res, b.key.id, b);
|
MapWrapper.set(res, b.key.id, b);
|
||||||
|
|
||||||
} else if (b instanceof Type) {
|
|
||||||
var s = bind(b).toClass(b);
|
|
||||||
MapWrapper.set(res, s.key.id, s);
|
|
||||||
|
|
||||||
} else if (b instanceof List) {
|
} else if (b instanceof List) {
|
||||||
_flattenBindings(b, res);
|
_flattenBindings(b, res);
|
||||||
|
|
||||||
} else if (b instanceof BindingBuilder) {
|
|
||||||
throw new InvalidBindingError(b.token);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
throw new InvalidBindingError(b);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return res;
|
return res;
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
/// This file contains tests that make sense only in Dart world, such as
|
||||||
|
/// verifying that things are valid constants.
|
||||||
|
|
||||||
|
import 'dart:mirrors';
|
||||||
|
import 'package:angular2/test_lib.dart';
|
||||||
|
import 'package:angular2/di.dart';
|
||||||
|
|
||||||
|
main() {
|
||||||
|
describe('Binding', () {
|
||||||
|
it('can create constant from token', () {
|
||||||
|
expect(const Binding(Foo).token).toBe(Foo);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can create constant from class', () {
|
||||||
|
expect(const Binding(Foo, toClass: Bar).toClass).toBe(Bar);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can create constant from value', () {
|
||||||
|
expect(const Binding(Foo, toValue: 5).toValue).toBe(5);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can create constant from alias', () {
|
||||||
|
expect(const Binding(Foo, toAlias: Bar).toAlias).toBe(Bar);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can create constant from factory', () {
|
||||||
|
expect(const Binding(Foo, toFactory: fn).toFactory).toBe(fn);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can create constant from async factory', () {
|
||||||
|
expect(const Binding(Foo, toAsyncFactory: fn).toAsyncFactory).toBe(fn);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can be used in annotation', () {
|
||||||
|
ClassMirror mirror = reflectType(Annotated);
|
||||||
|
var bindings = mirror.metadata[0].reflectee.bindings;
|
||||||
|
expect(bindings.length).toBe(6);
|
||||||
|
bindings.forEach((b) {
|
||||||
|
expect(b).toBeA(Binding);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
class Foo {}
|
||||||
|
class Bar extends Foo {}
|
||||||
|
fn() => null;
|
||||||
|
|
||||||
|
class Annotation {
|
||||||
|
final List bindings;
|
||||||
|
const Annotation(this.bindings);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Annotation(const [
|
||||||
|
const Binding(Foo),
|
||||||
|
const Binding(Foo, toClass: Bar),
|
||||||
|
const Binding(Foo, toValue: 5),
|
||||||
|
const Binding(Foo, toAlias: Bar),
|
||||||
|
const Binding(Foo, toFactory: fn),
|
||||||
|
const Binding(Foo, toAsyncFactory: fn),
|
||||||
|
])
|
||||||
|
class Annotated {}
|
Loading…
Reference in New Issue