Skip to content
This repository has been archived by the owner on Dec 6, 2017. It is now read-only.

Commit

Permalink
perf(injector): Do not closurize methods.
Browse files Browse the repository at this point in the history
  • Loading branch information
jbdeboer authored and pavelgj committed Apr 16, 2014
1 parent 1dedf6e commit 5f47cbd
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 43 deletions.
13 changes: 6 additions & 7 deletions lib/dynamic_injector.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,11 @@ class DynamicInjector extends Injector {
newFromParent(List<Module> modules, String name) =>
new DynamicInjector._fromParent(modules, this, name: name);

Object newInstanceOf(Type type, ObjectFactory getInstanceByKey, Injector requestor,
error(resolving, message, [appendDependency]),
Object newInstanceOf(Type type, ObjectFactory objFactory, Injector requestor,
List<Key> resolving) {
var classMirror = reflectType(type);
if (classMirror is TypedefMirror) {
throw new NoProviderError(error(resolving, 'No implementation provided '
throw new NoProviderError(Injector.error(resolving, 'No implementation provided '
'for ${getSymbolName(classMirror.qualifiedName)} typedef!'));
}

Expand All @@ -40,19 +39,19 @@ class DynamicInjector extends Injector {
ParameterMirror p = ctor.parameters[pos];
if (p.type.qualifiedName == #dynamic) {
var name = MirrorSystem.getName(p.simpleName);
throw new NoProviderError(error(resolving, "The '$name' parameter must be typed"));
throw new NoProviderError(Injector.error(resolving, "The '$name' parameter must be typed"));
}
if (p.type is TypedefMirror) {
throw new NoProviderError(
error(resolving, 'Cannot create new instance of a typedef ${p.type}'));
Injector.error(resolving, 'Cannot create new instance of a typedef ${p.type}'));
}
if (p.metadata.isNotEmpty) {
assert(p.metadata.length == 1);
var type = p.metadata.first.type.reflectedType;
return getInstanceByKey(new Key((p.type as ClassMirror).reflectedType,
return objFactory.getInstanceByKey(new Key((p.type as ClassMirror).reflectedType,
type), requestor, resolving);
} else {
return getInstanceByKey(new Key((p.type as ClassMirror).reflectedType),
return objFactory.getInstanceByKey(new Key((p.type as ClassMirror).reflectedType),
requestor, resolving);
}
}
Expand Down
29 changes: 16 additions & 13 deletions lib/injector.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ List<Key> _PRIMITIVE_TYPES = new UnmodifiableListView(<Key>[
new Key(bool)
]);

abstract class Injector {
abstract class ObjectFactory {
Object getInstanceByKey(Key key, Injector requester, List<Key> resolving);
}

abstract class Injector implements ObjectFactory {

/**
* Name of the injector or null of none is given.
Expand Down Expand Up @@ -75,7 +79,7 @@ abstract class Injector {
return types;
}

String _error(resolving, message, [appendDependency]) {
static String error(resolving, message, [appendDependency]) {
if (appendDependency != null) {
resolving.add(appendDependency);
}
Expand All @@ -85,13 +89,13 @@ abstract class Injector {
return '$message (resolving $graph)';
}

dynamic _getInstanceByKey(Key key, Injector requester, List<Key> resolving) {
Object getInstanceByKey(Key key, Injector requester, List<Key> resolving) {
assert(_checkKeyConditions(key, resolving));

// Do not bother checking the array until we are fairly deep.
if (resolving.length > 30 && resolving.contains(key)) {
throw new CircularDependencyError(
_error(resolving, 'Cannot resolve a circular dependency!', key));
Injector.error(resolving, 'Cannot resolve a circular dependency!', key));
}

var providerWithInjector = _getProviderWithInjectorForKey(key, resolving);
Expand All @@ -107,16 +111,16 @@ abstract class Injector {
if (!visible) {
if (injector.parent == null) {
throw new NoProviderError(
_error(resolving, 'No provider found for ${key}!', key));
Injector.error(resolving, 'No provider found for ${key}!', key));
}
injector =
injector.parent._getProviderWithInjectorForKey(key, resolving).injector;
}
return injector._getInstanceByKey(key, requester, resolving);
return injector.getInstanceByKey(key, requester, resolving);
}

resolving.add(key);
var value = provider.get(this, requester, _getInstanceByKey, _error, resolving);
var value = provider.get(this, requester, this, resolving);
resolving.removeLast();

// cache the value.
Expand All @@ -143,12 +147,12 @@ abstract class Injector {
new _TypeProvider(key.type), this);
}

throw new NoProviderError(_error(resolving, 'No provider found for ${key}!', key));
throw new NoProviderError(Injector.error(resolving, 'No provider found for ${key}!', key));
}

bool _checkKeyConditions(Key key, List resolving) {
if (_PRIMITIVE_TYPES.contains(key)) {
throw new NoProviderError(_error(resolving, 'Cannot inject a primitive type '
throw new NoProviderError(Injector.error(resolving, 'Cannot inject a primitive type '
'of ${key.type}!', key));
}
return true;
Expand All @@ -170,7 +174,7 @@ abstract class Injector {
* the token ([Type]) is instantiated.
*/
dynamic get(Type type, [Type annotation]) =>
_getInstanceByKey(new Key(type, annotation), this, []);
getInstanceByKey(new Key(type, annotation), this, []);

/**
* Get an instance for given key ([Key]).
Expand All @@ -181,7 +185,7 @@ abstract class Injector {
*
* If there is no binding for given key, injector asks parent injector.
*/
dynamic getByKey(Key key) => _getInstanceByKey(key, this, []);
dynamic getByKey(Key key) => getInstanceByKey(key, this, []);

/**
* Create a child injector.
Expand Down Expand Up @@ -214,7 +218,7 @@ abstract class Injector {
var providerWithInjector = _getProviderWithInjectorForKey(key, resolving);
var provider = providerWithInjector.provider;
forceNew._keyedFactory(key, (Injector inj) => provider.get(this,
inj, inj._getInstanceByKey, inj._error, resolving),
inj, inj, resolving),
visibility: provider.visibility);
});

Expand All @@ -228,7 +232,6 @@ abstract class Injector {
newFromParent(List<Module> modules, String name);

Object newInstanceOf(Type type, ObjectFactory factory, Injector requestor,
errorHandler(resolving, message, [appendDependency]),
List<Key> resolving);
}

Expand Down
11 changes: 4 additions & 7 deletions lib/injector_delagate.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,13 @@ class InjectorDelagate implements Injector {
Injector get parent => _injector.parent;

dynamic get(Type type, [Type annotation]) =>
_injector._getInstanceByKey(new Key(type, annotation), this, _resolving);
_injector.getInstanceByKey(new Key(type, annotation), this, _resolving);

dynamic getByKey(Key key) =>
_injector._getInstanceByKey(key, this, _resolving);
_injector.getInstanceByKey(key, this, _resolving);

dynamic _getInstanceByKey(Key key, Injector requester, List<Key> resolving) =>
_injector._getInstanceByKey(key, requester, resolving);

String _error(resolving, message, [appendDependency]) =>
_injector._error(resolving, message, appendDependency);
dynamic getInstanceByKey(Key key, Injector requester, List<Key> resolving) =>
_injector.getInstanceByKey(key, requester, resolving);

Injector createChild(List<Module> modules,
{List forceNewInstances, String name}) =>
Expand Down
16 changes: 5 additions & 11 deletions lib/module.dart
Original file line number Diff line number Diff line change
Expand Up @@ -113,23 +113,17 @@ class Module {
_providersCache == null || _childModules.any((m) => m._isDirty);
}

/** Deafault creation strategy is to instantiate on the defining injector. */
dynamic _defaultCreationStrategy(Injector requesting, Injector defining,
dynamic factory()) => factory();

/** By default all values are visible to child injectors. */
bool _defaultVisibility(_, __) => true;

typedef Object ObjectFactory(Key type, Injector requestor, List resolving);

abstract class _Provider {
final Visibility visibility;
final Type type;

_Provider(this.type, this.visibility);

dynamic get(Injector injector, Injector requestor,
ObjectFactory getInstanceByKey, error,
ObjectFactory objFactory,
List<Key> resolving);
}

Expand All @@ -140,16 +134,16 @@ class _ValueProvider extends _Provider {
: super(type, visibility);

dynamic get(Injector injector, Injector requestor,
ObjectFactory getInstanceByKey, error, resolving) => value;
ObjectFactory objFactory, resolving) => value;
}

class _TypeProvider extends _Provider {
_TypeProvider(type, [Visibility visibility]) : super(type, visibility);

dynamic get(Injector injector, Injector requestor,
ObjectFactory getInstanceByKey, error, resolving) {
ObjectFactory objFactory, resolving) {
return injector.newInstanceOf(
type, getInstanceByKey, requestor, error, resolving);
type, objFactory, requestor, resolving);
}
}

Expand All @@ -160,6 +154,6 @@ class _FactoryProvider extends _Provider {
: super(type, visibility);

dynamic get(Injector injector, Injector requestor,
ObjectFactory getInstanceByKey, error, resolving) =>
ObjectFactory objFactory, resolving) =>
factoryFn(new InjectorDelagate(injector, resolving));
}
8 changes: 4 additions & 4 deletions lib/static_injector.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@ class StaticInjector extends Injector {
newFromParent(List<Module> modules, String name) =>
new StaticInjector._fromParent(modules, this, name: name);

Object newInstanceOf(Type type, ObjectFactory getInstanceByKey,
Injector requestor, error, resolving) {
Object newInstanceOf(Type type, ObjectFactory objFactory,
Injector requestor, resolving) {
TypeFactory typeFactory = _getFactory(type);
if (typeFactory == null) {
throw new NoProviderError(
error(resolving, 'No type factory provided for $type!'));
Injector.error(resolving, 'No type factory provided for $type!'));
}
return typeFactory((type, [annotation]) =>
getInstanceByKey(new Key(type, annotation), requestor, resolving));
objFactory.getInstanceByKey(new Key(type, annotation), requestor, resolving));
}

TypeFactory _getFactory(Type key) {
Expand Down
2 changes: 1 addition & 1 deletion test/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ createInjectorSpec(String injectorName, InjectorFactory injectorFactory) {
injector.get(CircularA);
}, toThrow(CircularDependencyError, 'Cannot resolve a circular dependency! '
'(resolving CircularA -> '
'CircularB -> CircularA)'));
'CircularB -> CircularA'));
});


Expand Down

0 comments on commit 5f47cbd

Please sign in to comment.