@@ -4,7 +4,7 @@ import 'package:angular2/src/facade/lang.dart' show assertionsEnabled;
44
55import '../metadata.dart' ;
66import 'decorators.dart' ;
7- import 'provider.dart' show Provider, provide, noValueProvided;
7+ import 'provider.dart' show Provider, noValueProvided;
88import 'reflective_exceptions.dart'
99 show
1010 NoAnnotationError,
@@ -15,22 +15,18 @@ import 'reflective_key.dart';
1515/// [Dependency] is used by the framework to extend DI.
1616/// This is internal to Angular and should not be used directly.
1717class ReflectiveDependency {
18- ReflectiveKey key;
19- bool optional;
20- dynamic lowerBoundVisibility;
21- dynamic upperBoundVisibility;
22- List < dynamic > properties;
18+ final ReflectiveKey key;
19+ final bool optional;
20+ final dynamic lowerBoundVisibility;
21+ final dynamic upperBoundVisibility;
22+ final List properties;
2323 ReflectiveDependency (this .key, this .optional, this .lowerBoundVisibility,
2424 this .upperBoundVisibility, this .properties);
2525 static ReflectiveDependency fromKey (ReflectiveKey key) {
26- return new ReflectiveDependency (key, false , null , null , []);
26+ return new ReflectiveDependency (key, false , null , null , const []);
2727 }
2828}
2929
30- dynamic _identityPostProcess (obj) {
31- return obj;
32- }
33-
3430/// An internal resolved representation of a [Provider] used by the [Injector] .
3531///
3632/// It is usually created automatically by `Injector.resolveAndCreate` .
@@ -62,29 +58,26 @@ class ResolvedReflectiveProviderImpl implements ResolvedReflectiveBinding {
6258 ReflectiveKey key;
6359 List <ResolvedReflectiveFactory > resolvedFactories;
6460 bool multiProvider;
61+
6562 ResolvedReflectiveProviderImpl (
6663 this .key, this .resolvedFactories, this .multiProvider);
67- ResolvedReflectiveFactory get resolvedFactory {
68- return this .resolvedFactories[0 ];
69- }
64+
65+ ResolvedReflectiveFactory get resolvedFactory => resolvedFactories.first;
7066}
7167
7268/// An internal resolved representation of a factory function created by
7369/// resolving [Provider] .
7470class ResolvedReflectiveFactory {
75- Function factory ;
76- List <ReflectiveDependency > dependencies;
77- Function postProcess;
71+ final Function factory ;
72+ final List <ReflectiveDependency > dependencies;
7873
7974 /// Constructs a resolved factory.
8075 ///
8176 /// [factory] returns an instance of an object represented by a key.
8277 ///
8378 /// [dependencies] is a list of dependencies passed to [factory] as
8479 /// parameters.
85- ///
86- /// [postProcess] function is applied to the value constructed by [factory] .
87- ResolvedReflectiveFactory (this .factory , this .dependencies, this .postProcess);
80+ ResolvedReflectiveFactory (this .factory , this .dependencies);
8881}
8982
9083/// Resolve a single provider.
@@ -125,26 +118,27 @@ ResolvedReflectiveFactory resolveReflectiveFactory(Provider provider) {
125118 provider.dependencies,
126119 );
127120 }
128- } else if (provider.useClass != null ) {
129- var useClass = provider.useClass;
130- factoryFn = reflector.factory (useClass);
131- resolvedDeps = _dependenciesFor (useClass);
132- } else if (provider.useValue != noValueProvided) {
133- factoryFn = () => provider.useValue;
134- resolvedDeps = const < ReflectiveDependency > [];
135- } else if (provider.token is Type ) {
136- var useClass = provider.token;
137- factoryFn = reflector.factory (useClass);
138- resolvedDeps = _dependenciesFor (useClass);
139121 } else {
140- throw new InvalidProviderError .withCustomMessage (
141- provider, 'token is not a Type and no factory was specified' );
122+ var useClass = provider.useClass;
123+ if (useClass != null ) {
124+ factoryFn = reflector.factory (useClass);
125+ resolvedDeps = _dependenciesFor (useClass);
126+ } else {
127+ var useValue = provider.useValue;
128+ if (useValue != noValueProvided) {
129+ factoryFn = () => useValue;
130+ resolvedDeps = const < ReflectiveDependency > [];
131+ } else if (provider.token is Type ) {
132+ var useClass = provider.token;
133+ factoryFn = reflector.factory (useClass);
134+ resolvedDeps = _dependenciesFor (useClass);
135+ } else {
136+ throw new InvalidProviderError .withCustomMessage (
137+ provider, 'token is not a Type and no factory was specified' );
138+ }
139+ }
142140 }
143-
144- var postProcess = provider.useProperty != null
145- ? reflector.getter (provider.useProperty)
146- : _identityPostProcess;
147- return new ResolvedReflectiveFactory (factoryFn, resolvedDeps, postProcess);
141+ return new ResolvedReflectiveFactory (factoryFn, resolvedDeps);
148142}
149143
150144/// Converts the [Provider] into [ResolvedProvider] .
@@ -160,33 +154,35 @@ ResolvedReflectiveProvider resolveReflectiveProvider(Provider provider) {
160154List <ResolvedReflectiveProvider > resolveReflectiveProviders (
161155 List <dynamic /* Type | Provider | List < dynamic > */ > providers) {
162156 var normalized = _normalizeProviders (providers, []);
163- var resolved = normalized. map (resolveReflectiveProvider). toList () ;
164- return mergeResolvedReflectiveProviders (
165- resolved, new Map < num , ResolvedReflectiveProvider >())
166- .values
167- . toList ( );
157+ var resolved = < ResolvedReflectiveProvider > [] ;
158+ for ( int i = 0 , len = normalized.length; i < len; i ++ ) {
159+ resolved. add ( resolveReflectiveProvider (normalized[i]));
160+ }
161+ return mergeResolvedReflectiveProviders (resolved );
168162}
169163
170164/// Merges a list of ResolvedProviders into a list where
171165/// each key is contained exactly once and multi providers
172166/// have been merged.
173- Map <num , ResolvedReflectiveProvider > mergeResolvedReflectiveProviders (
174- List <ResolvedReflectiveProvider > providers,
175- Map <num , ResolvedReflectiveProvider > normalizedProvidersMap) {
176- for (var i = 0 ; i < providers.length; i++ ) {
167+ List <ResolvedReflectiveProvider > mergeResolvedReflectiveProviders (
168+ List <ResolvedReflectiveProvider > providers) {
169+ // Map used to dedup by provider key id.
170+ var idToProvider = < num , ResolvedReflectiveProvider > {};
171+ for (var i = 0 , len = providers.length; i < len; i++ ) {
177172 var provider = providers[i];
178- var existing = normalizedProvidersMap [provider.key.id];
173+ var existing = idToProvider [provider.key.id];
179174 if (existing != null ) {
180175 if (! identical (provider.multiProvider, existing.multiProvider)) {
181176 throw new MixingMultiProvidersWithRegularProvidersError (
182177 existing, provider);
183178 }
184179 if (provider.multiProvider) {
185- for (var j = 0 ; j < provider.resolvedFactories.length; j++ ) {
180+ var factories = provider.resolvedFactories;
181+ for (var j = 0 , len = factories.length; j < len; j++ ) {
186182 existing.resolvedFactories.add (provider.resolvedFactories[j]);
187183 }
188184 } else {
189- normalizedProvidersMap [provider.key.id] = provider;
185+ idToProvider [provider.key.id] = provider;
190186 }
191187 } else {
192188 var resolvedProvider;
@@ -196,28 +192,31 @@ Map<num, ResolvedReflectiveProvider> mergeResolvedReflectiveProviders(
196192 } else {
197193 resolvedProvider = provider;
198194 }
199- normalizedProvidersMap [provider.key.id] = resolvedProvider;
195+ idToProvider [provider.key.id] = resolvedProvider;
200196 }
201197 }
202- return normalizedProvidersMap ;
198+ return idToProvider.values. toList () ;
203199}
204200
201+ // Flattens list of lists of providers into a flat list. If any entry is a
202+ // Type it converts it to a useClass provider.
205203List <Provider > _normalizeProviders (
206204 List <dynamic /* Type | Provider | List < dynamic > */ > providers,
207205 List <Provider > res) {
208- providers.forEach ((b) {
206+ for (int i = 0 , len = providers.length; i < len; i++ ) {
207+ var b = providers[i];
209208 if (b is Type ) {
210- res.add (provide (b, useClass: b));
211- _normalizeProviders (const [], res);
209+ // If user listed a Type in provider list create Provide useClass: for it.
210+ // This is a shortcut to make provider lists easier to create.
211+ res.add (new Provider (b, useClass: b));
212212 } else if (b is Provider ) {
213- _normalizeProviders (const [], res);
214213 res.add (b);
215214 } else if (b is List ) {
216215 _normalizeProviders (b, res);
217216 } else {
218217 throw new InvalidProviderError (b);
219218 }
220- });
219+ }
221220 return res;
222221}
223222
@@ -226,10 +225,12 @@ List<ReflectiveDependency> constructDependencies(
226225 if (dependencies == null ) {
227226 return _dependenciesFor (typeOrFunc);
228227 } else {
229- List <List <dynamic >> params = dependencies.map ((t) => [t]).toList ();
230- return dependencies
231- .map ((t) => _extractToken (typeOrFunc, t, params))
232- .toList ();
228+ var deps = < ReflectiveDependency > [];
229+ for (int i = 0 , len = dependencies.length; i < len; i++ ) {
230+ deps.add (_extractTokenUnwrappedParameters (
231+ typeOrFunc, dependencies[i], dependencies));
232+ }
233+ return deps;
233234 }
234235}
235236
@@ -288,6 +289,56 @@ ReflectiveDependency _extractToken(
288289 token, optional, lowerBoundVisibility, upperBoundVisibility, depProps);
289290}
290291
292+ // Same as _extractToken but doesn't expect list wrapped parameters. This is
293+ // to reduce GC by eliminating list allocations for each parameter.
294+ ReflectiveDependency _extractTokenUnwrappedParameters (
295+ typeOrFunc, metadata, List <dynamic > params) {
296+ var depProps = [];
297+ var token;
298+ var optional = false ;
299+ if (metadata is ! List ) {
300+ if (metadata is Inject ) {
301+ return _createDependency (metadata.token, optional, null , null , depProps);
302+ } else {
303+ return _createDependency (metadata, optional, null , null , depProps);
304+ }
305+ }
306+ var lowerBoundVisibility;
307+ var upperBoundVisibility;
308+ for (var i = 0 ; i < metadata.length; ++ i) {
309+ var paramMetadata = metadata[i];
310+ if (paramMetadata is Type ) {
311+ token = paramMetadata;
312+ } else if (paramMetadata is Inject ) {
313+ token = paramMetadata.token;
314+ } else if (paramMetadata is Optional ) {
315+ optional = true ;
316+ } else if (paramMetadata is Self ) {
317+ upperBoundVisibility = paramMetadata;
318+ } else if (paramMetadata is Host ) {
319+ upperBoundVisibility = paramMetadata;
320+ } else if (paramMetadata is SkipSelf ) {
321+ lowerBoundVisibility = paramMetadata;
322+ } else if (paramMetadata is DependencyMetadata ) {
323+ if (paramMetadata.token != null ) {
324+ token = paramMetadata.token;
325+ }
326+ depProps.add (paramMetadata);
327+ }
328+ }
329+ if (token == null ) {
330+ // Since we have rare failure, wrap parameter types into a format that
331+ // NoAnnotationError expects in reflective mode.
332+ var paramList = < List <dynamic >> [];
333+ for (var param in params) {
334+ paramList.add ([param]);
335+ }
336+ throw new NoAnnotationError (typeOrFunc, params);
337+ }
338+ return _createDependency (
339+ token, optional, lowerBoundVisibility, upperBoundVisibility, depProps);
340+ }
341+
291342ReflectiveDependency _createDependency (
292343 token, optional, lowerBoundVisibility, upperBoundVisibility, depProps) {
293344 return new ReflectiveDependency (ReflectiveKey .get (token), optional,
0 commit comments