@alterior/di 3.14.3 → 3.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/injection/facade/errors.d.ts +1 -1
- package/dist/injection/facade/errors.d.ts.map +1 -1
- package/dist/injection/facade/errors.js +1 -1
- package/dist/injection/facade/errors.js.map +1 -1
- package/dist/injection/injector.js.map +1 -1
- package/dist/injection/metadata/annotations.d.ts.map +1 -1
- package/dist/injection/metadata/annotations.js.map +1 -1
- package/dist/injection/reflection/reflection_capabilities.d.ts.map +1 -1
- package/dist/injection/reflection/reflection_capabilities.js.map +1 -1
- package/dist/injection/reflective_injector.d.ts.map +1 -1
- package/dist/injection/reflective_injector.js +2 -3
- package/dist/injection/reflective_injector.js.map +1 -1
- package/dist/injection/reflective_injector.test.js.map +1 -1
- package/dist/modules.d.ts +2 -2
- package/dist/modules.d.ts.map +1 -1
- package/dist/modules.js +1 -1
- package/dist/modules.js.map +1 -1
- package/dist.esm/injection/facade/errors.d.ts +1 -1
- package/dist.esm/injection/facade/errors.d.ts.map +1 -1
- package/dist.esm/injection/facade/errors.js +1 -1
- package/dist.esm/injection/facade/errors.js.map +1 -1
- package/dist.esm/injection/injector.js.map +1 -1
- package/dist.esm/injection/metadata/annotations.d.ts.map +1 -1
- package/dist.esm/injection/metadata/annotations.js.map +1 -1
- package/dist.esm/injection/reflection/reflection_capabilities.d.ts.map +1 -1
- package/dist.esm/injection/reflection/reflection_capabilities.js.map +1 -1
- package/dist.esm/injection/reflective_injector.d.ts.map +1 -1
- package/dist.esm/injection/reflective_injector.js +2 -3
- package/dist.esm/injection/reflective_injector.js.map +1 -1
- package/dist.esm/injection/reflective_injector.test.js.map +1 -1
- package/dist.esm/modules.d.ts +2 -2
- package/dist.esm/modules.d.ts.map +1 -1
- package/dist.esm/modules.js +1 -1
- package/dist.esm/modules.js.map +1 -1
- package/package.json +3 -3
- package/src/injection/facade/errors.ts +1 -1
- package/src/injection/injector.ts +1 -1
- package/src/injection/metadata/annotations.ts +2 -2
- package/src/injection/reflection/reflection_capabilities.ts +162 -162
- package/src/injection/reflective_injector.ts +430 -431
- package/src/modules.ts +5 -5
|
@@ -13,10 +13,10 @@ import { Provider, ClassProvider, ProviderWithDependencies, isTypeProvider } fro
|
|
|
13
13
|
import { cyclicDependencyError, instantiationError, noProviderError, outOfBoundsError } from './reflective_errors';
|
|
14
14
|
import { ReflectiveKey } from './reflective_key';
|
|
15
15
|
import {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
ReflectiveDependency,
|
|
17
|
+
ResolvedReflectiveFactory,
|
|
18
|
+
ResolvedReflectiveProvider,
|
|
19
|
+
resolveReflectiveProviders,
|
|
20
20
|
} from './reflective_provider';
|
|
21
21
|
import { Annotation } from '@alterior/annotations';
|
|
22
22
|
|
|
@@ -59,489 +59,488 @@ const UNDEFINED = new Object();
|
|
|
59
59
|
* @stable
|
|
60
60
|
*/
|
|
61
61
|
export abstract class ReflectiveInjector implements Injector {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Resolves an array of providers and creates an injector from those providers.
|
|
101
|
-
*
|
|
102
|
-
* The passed-in providers can be an array of `Type`, {@link Provider},
|
|
103
|
-
* or a recursive array of more providers.
|
|
104
|
-
*
|
|
105
|
-
* ### Example ([live demo](http://plnkr.co/edit/ePOccA?p=preview))
|
|
106
|
-
*
|
|
107
|
-
* ```typescript
|
|
108
|
-
* @Injectable()
|
|
109
|
-
* class Engine {
|
|
110
|
-
* }
|
|
111
|
-
*
|
|
112
|
-
* @Injectable()
|
|
113
|
-
* class Car {
|
|
114
|
-
* constructor(public engine:Engine) {}
|
|
115
|
-
* }
|
|
116
|
-
*
|
|
117
|
-
* var injector = ReflectiveInjector.resolveAndCreate([Car, Engine]);
|
|
118
|
-
* expect(injector.get(Car) instanceof Car).toBe(true);
|
|
119
|
-
* ```
|
|
120
|
-
*
|
|
121
|
-
* This function is slower than the corresponding `fromResolvedProviders`
|
|
122
|
-
* because it needs to resolve the passed-in providers first.
|
|
123
|
-
* See {@link Injector#resolve} and {@link Injector#fromResolvedProviders}.
|
|
124
|
-
*/
|
|
125
|
-
static resolveAndCreate(providers: Provider[], parent?: Injector): ReflectiveInjector {
|
|
126
|
-
const ResolvedReflectiveProviders = ReflectiveInjector.resolve(providers);
|
|
127
|
-
return ReflectiveInjector.fromResolvedProviders(ResolvedReflectiveProviders, parent);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Extract the dependencies of the given providers
|
|
132
|
-
* @param providers
|
|
133
|
-
*/
|
|
134
|
-
static reflectDependencies(provider : Provider): ProviderWithDependencies {
|
|
135
|
-
if (isTypeProvider(provider)) {
|
|
136
|
-
provider = {
|
|
137
|
-
provide: provider,
|
|
138
|
-
useClass: <ConcreteType<any>>provider
|
|
139
|
-
};
|
|
62
|
+
/**
|
|
63
|
+
* Turns an array of provider definitions into an array of resolved providers.
|
|
64
|
+
*
|
|
65
|
+
* A resolution is a process of flattening multiple nested arrays and converting individual
|
|
66
|
+
* providers into an array of {@link ResolvedReflectiveProvider}s.
|
|
67
|
+
*
|
|
68
|
+
* ### Example ([live demo](http://plnkr.co/edit/AiXTHi?p=preview))
|
|
69
|
+
*
|
|
70
|
+
* ```typescript
|
|
71
|
+
* @Injectable()
|
|
72
|
+
* class Engine {
|
|
73
|
+
* }
|
|
74
|
+
*
|
|
75
|
+
* @Injectable()
|
|
76
|
+
* class Car {
|
|
77
|
+
* constructor(public engine:Engine) {}
|
|
78
|
+
* }
|
|
79
|
+
*
|
|
80
|
+
* var providers = ReflectiveInjector.resolve([Car, [[Engine]]]);
|
|
81
|
+
*
|
|
82
|
+
* expect(providers.length).toEqual(2);
|
|
83
|
+
*
|
|
84
|
+
* expect(providers[0] instanceof ResolvedReflectiveProvider).toBe(true);
|
|
85
|
+
* expect(providers[0].key.displayName).toBe("Car");
|
|
86
|
+
* expect(providers[0].dependencies.length).toEqual(1);
|
|
87
|
+
* expect(providers[0].factory).toBeDefined();
|
|
88
|
+
*
|
|
89
|
+
* expect(providers[1].key.displayName).toBe("Engine");
|
|
90
|
+
* });
|
|
91
|
+
* ```
|
|
92
|
+
*
|
|
93
|
+
* See {@link ReflectiveInjector#fromResolvedProviders} for more info.
|
|
94
|
+
*/
|
|
95
|
+
static resolve(providers: Provider[]): ResolvedReflectiveProvider[] {
|
|
96
|
+
return resolveReflectiveProviders(providers);
|
|
140
97
|
}
|
|
141
98
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
99
|
+
/**
|
|
100
|
+
* Resolves an array of providers and creates an injector from those providers.
|
|
101
|
+
*
|
|
102
|
+
* The passed-in providers can be an array of `Type`, {@link Provider},
|
|
103
|
+
* or a recursive array of more providers.
|
|
104
|
+
*
|
|
105
|
+
* ### Example ([live demo](http://plnkr.co/edit/ePOccA?p=preview))
|
|
106
|
+
*
|
|
107
|
+
* ```typescript
|
|
108
|
+
* @Injectable()
|
|
109
|
+
* class Engine {
|
|
110
|
+
* }
|
|
111
|
+
*
|
|
112
|
+
* @Injectable()
|
|
113
|
+
* class Car {
|
|
114
|
+
* constructor(public engine:Engine) {}
|
|
115
|
+
* }
|
|
116
|
+
*
|
|
117
|
+
* var injector = ReflectiveInjector.resolveAndCreate([Car, Engine]);
|
|
118
|
+
* expect(injector.get(Car) instanceof Car).toBe(true);
|
|
119
|
+
* ```
|
|
120
|
+
*
|
|
121
|
+
* This function is slower than the corresponding `fromResolvedProviders`
|
|
122
|
+
* because it needs to resolve the passed-in providers first.
|
|
123
|
+
* See {@link Injector#resolve} and {@link Injector#fromResolvedProviders}.
|
|
124
|
+
*/
|
|
125
|
+
static resolveAndCreate(providers: Provider[], parent?: Injector): ReflectiveInjector {
|
|
126
|
+
const ResolvedReflectiveProviders = ReflectiveInjector.resolve(providers);
|
|
127
|
+
return ReflectiveInjector.fromResolvedProviders(ResolvedReflectiveProviders, parent);
|
|
156
128
|
}
|
|
157
129
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
130
|
+
/**
|
|
131
|
+
* Extract the dependencies of the given providers
|
|
132
|
+
* @param providers
|
|
133
|
+
*/
|
|
134
|
+
static reflectDependencies(provider: Provider): ProviderWithDependencies {
|
|
135
|
+
if (isTypeProvider(provider)) {
|
|
136
|
+
provider = {
|
|
137
|
+
provide: provider,
|
|
138
|
+
useClass: <ConcreteType<any>>provider
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if ('useClass' in provider)
|
|
143
|
+
return provider;
|
|
162
144
|
|
|
163
|
-
let
|
|
164
|
-
let optionalAnnotation = <OptionalAnnotation>paramAnnotations.find(x => x instanceof OptionalAnnotation);
|
|
145
|
+
let classProvider: ClassProvider = <any>provider;
|
|
165
146
|
|
|
166
|
-
|
|
147
|
+
const paramsAnnotations = Annotation.getAllForConstructorParameters(classProvider.useClass);
|
|
148
|
+
let params = Reflect.getOwnMetadata('design:paramtypes', classProvider.useClass);
|
|
149
|
+
let deps = [];
|
|
167
150
|
|
|
168
|
-
if (
|
|
169
|
-
|
|
151
|
+
if (classProvider.useClass.length > 0 && typeof params === 'undefined') {
|
|
152
|
+
throw new Error(
|
|
153
|
+
`missing-reflection: No reflection metadata available `
|
|
154
|
+
+ `for ${classProvider.useClass.name}`
|
|
155
|
+
);
|
|
170
156
|
}
|
|
171
157
|
|
|
172
|
-
|
|
158
|
+
if (params && params.length > 0) {
|
|
159
|
+
for (let i = 0; i < params.length; ++i) {
|
|
160
|
+
let param = params[i];
|
|
161
|
+
let paramAnnotations = paramsAnnotations[i] || [];
|
|
173
162
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
163
|
+
let injectAnnotation = <InjectAnnotation>paramAnnotations.find(x => x instanceof InjectAnnotation);
|
|
164
|
+
let optionalAnnotation = <OptionalAnnotation>paramAnnotations.find(x => x instanceof OptionalAnnotation);
|
|
165
|
+
|
|
166
|
+
let token = param;
|
|
167
|
+
|
|
168
|
+
if (injectAnnotation) {
|
|
169
|
+
token = injectAnnotation.token;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
let dep: any = token;
|
|
173
|
+
|
|
174
|
+
if (optionalAnnotation) {
|
|
175
|
+
dep = [Optional, token];
|
|
176
|
+
} else {
|
|
177
|
+
dep = token;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
deps.push(dep);
|
|
181
|
+
}
|
|
178
182
|
}
|
|
179
183
|
|
|
180
|
-
|
|
181
|
-
|
|
184
|
+
return <ProviderWithDependencies>{
|
|
185
|
+
provide: classProvider.provide,
|
|
186
|
+
useClass: classProvider.useClass,
|
|
187
|
+
deps
|
|
188
|
+
}
|
|
182
189
|
}
|
|
183
190
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
191
|
+
/**
|
|
192
|
+
* Creates an injector from previously resolved providers.
|
|
193
|
+
*
|
|
194
|
+
* This API is the recommended way to construct injectors in performance-sensitive parts.
|
|
195
|
+
*
|
|
196
|
+
* ### Example ([live demo](http://plnkr.co/edit/KrSMci?p=preview))
|
|
197
|
+
*
|
|
198
|
+
* ```typescript
|
|
199
|
+
* @Injectable()
|
|
200
|
+
* class Engine {
|
|
201
|
+
* }
|
|
202
|
+
*
|
|
203
|
+
* @Injectable()
|
|
204
|
+
* class Car {
|
|
205
|
+
* constructor(public engine:Engine) {}
|
|
206
|
+
* }
|
|
207
|
+
*
|
|
208
|
+
* var providers = ReflectiveInjector.resolve([Car, Engine]);
|
|
209
|
+
* var injector = ReflectiveInjector.fromResolvedProviders(providers);
|
|
210
|
+
* expect(injector.get(Car) instanceof Car).toBe(true);
|
|
211
|
+
* ```
|
|
212
|
+
* @experimental
|
|
213
|
+
*/
|
|
214
|
+
static fromResolvedProviders(providers: ResolvedReflectiveProvider[], parent?: Injector): ReflectiveInjector {
|
|
215
|
+
// tslint:disable-next-line:no-use-before-declare
|
|
216
|
+
return new ReflectiveInjector_(providers, parent);
|
|
188
217
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
abstract resolveAndInstantiate(provider: Provider): any;
|
|
316
|
-
|
|
317
|
-
/**
|
|
318
|
-
* Instantiates an object using a resolved provider in the context of the injector.
|
|
319
|
-
*
|
|
320
|
-
* The created object does not get cached by the injector.
|
|
321
|
-
*
|
|
322
|
-
* ### Example ([live demo](http://plnkr.co/edit/ptCImQ?p=preview))
|
|
323
|
-
*
|
|
324
|
-
* ```typescript
|
|
325
|
-
* @Injectable()
|
|
326
|
-
* class Engine {
|
|
327
|
-
* }
|
|
328
|
-
*
|
|
329
|
-
* @Injectable()
|
|
330
|
-
* class Car {
|
|
331
|
-
* constructor(public engine:Engine) {}
|
|
332
|
-
* }
|
|
333
|
-
*
|
|
334
|
-
* var injector = ReflectiveInjector.resolveAndCreate([Engine]);
|
|
335
|
-
* var carProvider = ReflectiveInjector.resolve([Car])[0];
|
|
336
|
-
* var car = injector.instantiateResolved(carProvider);
|
|
337
|
-
* expect(car.engine).toBe(injector.get(Engine));
|
|
338
|
-
* expect(car).not.toBe(injector.instantiateResolved(carProvider));
|
|
339
|
-
* ```
|
|
340
|
-
*/
|
|
341
|
-
abstract instantiateResolved(provider: ResolvedReflectiveProvider): any;
|
|
342
|
-
|
|
343
|
-
abstract get(token: any, notFoundValue?: any): any;
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Parent of this injector.
|
|
221
|
+
*
|
|
222
|
+
* <!-- TODO: Add a link to the section of the user guide talking about hierarchical injection.
|
|
223
|
+
* -->
|
|
224
|
+
*
|
|
225
|
+
* ### Example ([live demo](http://plnkr.co/edit/eosMGo?p=preview))
|
|
226
|
+
*
|
|
227
|
+
* ```typescript
|
|
228
|
+
* var parent = ReflectiveInjector.resolveAndCreate([]);
|
|
229
|
+
* var child = parent.resolveAndCreateChild([]);
|
|
230
|
+
* expect(child.parent).toBe(parent);
|
|
231
|
+
* ```
|
|
232
|
+
*/
|
|
233
|
+
abstract get parent(): Injector | null;
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Resolves an array of providers and creates a child injector from those providers.
|
|
237
|
+
*
|
|
238
|
+
* <!-- TODO: Add a link to the section of the user guide talking about hierarchical injection.
|
|
239
|
+
* -->
|
|
240
|
+
*
|
|
241
|
+
* The passed-in providers can be an array of `Type`, {@link Provider},
|
|
242
|
+
* or a recursive array of more providers.
|
|
243
|
+
*
|
|
244
|
+
* ### Example ([live demo](http://plnkr.co/edit/opB3T4?p=preview))
|
|
245
|
+
*
|
|
246
|
+
* ```typescript
|
|
247
|
+
* class ParentProvider {}
|
|
248
|
+
* class ChildProvider {}
|
|
249
|
+
*
|
|
250
|
+
* var parent = ReflectiveInjector.resolveAndCreate([ParentProvider]);
|
|
251
|
+
* var child = parent.resolveAndCreateChild([ChildProvider]);
|
|
252
|
+
*
|
|
253
|
+
* expect(child.get(ParentProvider) instanceof ParentProvider).toBe(true);
|
|
254
|
+
* expect(child.get(ChildProvider) instanceof ChildProvider).toBe(true);
|
|
255
|
+
* expect(child.get(ParentProvider)).toBe(parent.get(ParentProvider));
|
|
256
|
+
* ```
|
|
257
|
+
*
|
|
258
|
+
* This function is slower than the corresponding `createChildFromResolved`
|
|
259
|
+
* because it needs to resolve the passed-in providers first.
|
|
260
|
+
* See {@link Injector#resolve} and {@link Injector#createChildFromResolved}.
|
|
261
|
+
*/
|
|
262
|
+
abstract resolveAndCreateChild(providers: Provider[]): ReflectiveInjector;
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Creates a child injector from previously resolved providers.
|
|
266
|
+
*
|
|
267
|
+
* <!-- TODO: Add a link to the section of the user guide talking about hierarchical injection.
|
|
268
|
+
* -->
|
|
269
|
+
*
|
|
270
|
+
* This API is the recommended way to construct injectors in performance-sensitive parts.
|
|
271
|
+
*
|
|
272
|
+
* ### Example ([live demo](http://plnkr.co/edit/VhyfjN?p=preview))
|
|
273
|
+
*
|
|
274
|
+
* ```typescript
|
|
275
|
+
* class ParentProvider {}
|
|
276
|
+
* class ChildProvider {}
|
|
277
|
+
*
|
|
278
|
+
* var parentProviders = ReflectiveInjector.resolve([ParentProvider]);
|
|
279
|
+
* var childProviders = ReflectiveInjector.resolve([ChildProvider]);
|
|
280
|
+
*
|
|
281
|
+
* var parent = ReflectiveInjector.fromResolvedProviders(parentProviders);
|
|
282
|
+
* var child = parent.createChildFromResolved(childProviders);
|
|
283
|
+
*
|
|
284
|
+
* expect(child.get(ParentProvider) instanceof ParentProvider).toBe(true);
|
|
285
|
+
* expect(child.get(ChildProvider) instanceof ChildProvider).toBe(true);
|
|
286
|
+
* expect(child.get(ParentProvider)).toBe(parent.get(ParentProvider));
|
|
287
|
+
* ```
|
|
288
|
+
*/
|
|
289
|
+
abstract createChildFromResolved(providers: ResolvedReflectiveProvider[]): ReflectiveInjector;
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Resolves a provider and instantiates an object in the context of the injector.
|
|
293
|
+
*
|
|
294
|
+
* The created object does not get cached by the injector.
|
|
295
|
+
*
|
|
296
|
+
* ### Example ([live demo](http://plnkr.co/edit/yvVXoB?p=preview))
|
|
297
|
+
*
|
|
298
|
+
* ```typescript
|
|
299
|
+
* @Injectable()
|
|
300
|
+
* class Engine {
|
|
301
|
+
* }
|
|
302
|
+
*
|
|
303
|
+
* @Injectable()
|
|
304
|
+
* class Car {
|
|
305
|
+
* constructor(public engine:Engine) {}
|
|
306
|
+
* }
|
|
307
|
+
*
|
|
308
|
+
* var injector = ReflectiveInjector.resolveAndCreate([Engine]);
|
|
309
|
+
*
|
|
310
|
+
* var car = injector.resolveAndInstantiate(Car);
|
|
311
|
+
* expect(car.engine).toBe(injector.get(Engine));
|
|
312
|
+
* expect(car).not.toBe(injector.resolveAndInstantiate(Car));
|
|
313
|
+
* ```
|
|
314
|
+
*/
|
|
315
|
+
abstract resolveAndInstantiate(provider: Provider): any;
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Instantiates an object using a resolved provider in the context of the injector.
|
|
319
|
+
*
|
|
320
|
+
* The created object does not get cached by the injector.
|
|
321
|
+
*
|
|
322
|
+
* ### Example ([live demo](http://plnkr.co/edit/ptCImQ?p=preview))
|
|
323
|
+
*
|
|
324
|
+
* ```typescript
|
|
325
|
+
* @Injectable()
|
|
326
|
+
* class Engine {
|
|
327
|
+
* }
|
|
328
|
+
*
|
|
329
|
+
* @Injectable()
|
|
330
|
+
* class Car {
|
|
331
|
+
* constructor(public engine:Engine) {}
|
|
332
|
+
* }
|
|
333
|
+
*
|
|
334
|
+
* var injector = ReflectiveInjector.resolveAndCreate([Engine]);
|
|
335
|
+
* var carProvider = ReflectiveInjector.resolve([Car])[0];
|
|
336
|
+
* var car = injector.instantiateResolved(carProvider);
|
|
337
|
+
* expect(car.engine).toBe(injector.get(Engine));
|
|
338
|
+
* expect(car).not.toBe(injector.instantiateResolved(carProvider));
|
|
339
|
+
* ```
|
|
340
|
+
*/
|
|
341
|
+
abstract instantiateResolved(provider: ResolvedReflectiveProvider): any;
|
|
342
|
+
|
|
343
|
+
abstract get(token: any, notFoundValue?: any): any;
|
|
344
344
|
}
|
|
345
345
|
|
|
346
346
|
// tslint:disable-next-line:class-name
|
|
347
347
|
export class ReflectiveInjector_ implements ReflectiveInjector {
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
348
|
+
/** @internal */
|
|
349
|
+
_constructionCounter: number = 0;
|
|
350
|
+
/** @internal */
|
|
351
|
+
public _providers: ResolvedReflectiveProvider[];
|
|
352
|
+
/** @internal */
|
|
353
|
+
public _parent: Injector | null;
|
|
354
|
+
|
|
355
|
+
keyIds: number[];
|
|
356
|
+
objs: any[];
|
|
357
|
+
/**
|
|
358
|
+
* Private
|
|
359
|
+
*/
|
|
360
|
+
constructor(_providers: ResolvedReflectiveProvider[], _parent?: Injector) {
|
|
361
|
+
this._providers = _providers;
|
|
362
|
+
this._parent = _parent || null;
|
|
363
|
+
|
|
364
|
+
const len = _providers.length;
|
|
365
|
+
|
|
366
|
+
this.keyIds = new Array(len);
|
|
367
|
+
this.objs = new Array(len);
|
|
368
|
+
|
|
369
|
+
for (let i = 0; i < len; i++) {
|
|
370
|
+
this.keyIds[i] = _providers[i].key.id;
|
|
371
|
+
this.objs[i] = UNDEFINED;
|
|
372
|
+
}
|
|
372
373
|
}
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
private _useSelf = new SelfAnnotation();
|
|
376
374
|
|
|
377
|
-
|
|
378
|
-
return this._getByKey(ReflectiveKey.get(token), options?.self ? this._useSelf: null, notFoundValue);
|
|
379
|
-
}
|
|
375
|
+
private _useSelf = new SelfAnnotation();
|
|
380
376
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
377
|
+
get(token: any, notFoundValue: any = THROW_IF_NOT_FOUND, options?: InjectorGetOptions): any {
|
|
378
|
+
return this._getByKey(ReflectiveKey.get(token), options?.self ? this._useSelf : null, notFoundValue);
|
|
379
|
+
}
|
|
384
380
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
}
|
|
381
|
+
get parent(): Injector | null {
|
|
382
|
+
return this._parent;
|
|
383
|
+
}
|
|
389
384
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
}
|
|
385
|
+
resolveAndCreateChild(providers: Provider[]): ReflectiveInjector {
|
|
386
|
+
const ResolvedReflectiveProviders = ReflectiveInjector.resolve(providers);
|
|
387
|
+
return this.createChildFromResolved(ResolvedReflectiveProviders);
|
|
388
|
+
}
|
|
395
389
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
390
|
+
createChildFromResolved(providers: ResolvedReflectiveProvider[]): ReflectiveInjector {
|
|
391
|
+
const inj = new ReflectiveInjector_(providers);
|
|
392
|
+
inj._parent = this;
|
|
393
|
+
return inj;
|
|
394
|
+
}
|
|
399
395
|
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
396
|
+
resolveAndInstantiate(provider: Provider): any {
|
|
397
|
+
return this.instantiateResolved(ReflectiveInjector.resolve([provider])[0]);
|
|
398
|
+
}
|
|
403
399
|
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
throw outOfBoundsError(index);
|
|
400
|
+
instantiateResolved(provider: ResolvedReflectiveProvider): any {
|
|
401
|
+
return this._instantiateProvider(provider);
|
|
407
402
|
}
|
|
408
|
-
return this._providers[index];
|
|
409
|
-
}
|
|
410
403
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
404
|
+
getProviderAtIndex(index: number): ResolvedReflectiveProvider {
|
|
405
|
+
if (index < 0 || index >= this._providers.length) {
|
|
406
|
+
throw outOfBoundsError(index);
|
|
407
|
+
}
|
|
408
|
+
return this._providers[index];
|
|
415
409
|
}
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
private _instantiateProvider(provider: ResolvedReflectiveProvider): any {
|
|
424
|
-
if (provider.multiProvider) {
|
|
425
|
-
const res = new Array(provider.resolvedFactories.length);
|
|
426
|
-
for (let i = 0; i < provider.resolvedFactories.length; ++i) {
|
|
427
|
-
res[i] = this._instantiate(provider, provider.resolvedFactories[i]);
|
|
428
|
-
}
|
|
429
|
-
return res;
|
|
430
|
-
} else {
|
|
431
|
-
return this._instantiate(provider, provider.resolvedFactories[0]);
|
|
410
|
+
|
|
411
|
+
/** @internal */
|
|
412
|
+
_new(provider: ResolvedReflectiveProvider): any {
|
|
413
|
+
if (this._constructionCounter++ > this._getMaxNumberOfObjects()) {
|
|
414
|
+
throw cyclicDependencyError(this, provider.key);
|
|
415
|
+
}
|
|
416
|
+
return this._instantiateProvider(provider);
|
|
432
417
|
}
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
const factory = ResolvedReflectiveFactory.factory;
|
|
437
|
-
|
|
438
|
-
let deps: any[];
|
|
439
|
-
try {
|
|
440
|
-
deps = ResolvedReflectiveFactory.dependencies.map(dep => this._getByReflectiveDependency(dep));
|
|
441
|
-
} catch (e) {
|
|
442
|
-
if (e.addKey) {
|
|
443
|
-
e.addKey(this, provider.key);
|
|
444
|
-
}
|
|
445
|
-
throw e;
|
|
418
|
+
|
|
419
|
+
private _getMaxNumberOfObjects(): number {
|
|
420
|
+
return this.objs.length;
|
|
446
421
|
}
|
|
447
422
|
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
423
|
+
private _instantiateProvider(provider: ResolvedReflectiveProvider): any {
|
|
424
|
+
if (provider.multiProvider) {
|
|
425
|
+
const res = new Array(provider.resolvedFactories.length);
|
|
426
|
+
for (let i = 0; i < provider.resolvedFactories.length; ++i) {
|
|
427
|
+
res[i] = this._instantiate(provider, provider.resolvedFactories[i]);
|
|
428
|
+
}
|
|
429
|
+
return res;
|
|
430
|
+
} else {
|
|
431
|
+
return this._instantiate(provider, provider.resolvedFactories[0]);
|
|
432
|
+
}
|
|
455
433
|
}
|
|
456
434
|
|
|
457
|
-
|
|
458
|
-
|
|
435
|
+
private _instantiate(provider: ResolvedReflectiveProvider, ResolvedReflectiveFactory: ResolvedReflectiveFactory): any {
|
|
436
|
+
const factory = ResolvedReflectiveFactory.factory;
|
|
437
|
+
|
|
438
|
+
let deps: any[];
|
|
439
|
+
try {
|
|
440
|
+
deps = ResolvedReflectiveFactory.dependencies.map(dep => this._getByReflectiveDependency(dep));
|
|
441
|
+
} catch (e: any) {
|
|
442
|
+
if (e.addKey)
|
|
443
|
+
e.addKey(this, provider.key);
|
|
444
|
+
throw e;
|
|
445
|
+
}
|
|
459
446
|
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
447
|
+
let obj: any;
|
|
448
|
+
try {
|
|
449
|
+
Injector.run(this, () => {
|
|
450
|
+
obj = factory(...deps);
|
|
451
|
+
});
|
|
452
|
+
} catch (e: any) {
|
|
453
|
+
throw instantiationError(this, e, e.stack, provider.key);
|
|
454
|
+
}
|
|
463
455
|
|
|
464
|
-
|
|
465
|
-
// tslint:disable-next-line:no-use-before-declare
|
|
466
|
-
if (key === INJECTOR_KEY) {
|
|
467
|
-
return this;
|
|
456
|
+
return obj;
|
|
468
457
|
}
|
|
469
458
|
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
} else {
|
|
473
|
-
return this._getByKeyDefault(key, notFoundValue, visibility);
|
|
459
|
+
private _getByReflectiveDependency(dep: ReflectiveDependency): any {
|
|
460
|
+
return this._getByKey(dep.key, dep.visibility, dep.optional ? null : THROW_IF_NOT_FOUND);
|
|
474
461
|
}
|
|
475
|
-
}
|
|
476
462
|
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
this.objs[i] = this._new(this._providers[i]);
|
|
463
|
+
private _getByKey(key: ReflectiveKey, visibility: SelfAnnotation | SkipSelfAnnotation | null, notFoundValue: any): any {
|
|
464
|
+
// tslint:disable-next-line:no-use-before-declare
|
|
465
|
+
if (key === INJECTOR_KEY) {
|
|
466
|
+
return this;
|
|
482
467
|
}
|
|
483
468
|
|
|
484
|
-
|
|
485
|
-
|
|
469
|
+
if (visibility instanceof SelfAnnotation) {
|
|
470
|
+
return this._getByKeySelf(key, notFoundValue);
|
|
471
|
+
} else {
|
|
472
|
+
return this._getByKeyDefault(key, notFoundValue, visibility);
|
|
473
|
+
}
|
|
486
474
|
}
|
|
487
475
|
|
|
488
|
-
|
|
489
|
-
|
|
476
|
+
private _getObjByKeyId(keyId: number): any {
|
|
477
|
+
for (let i = 0; i < this.keyIds.length; i++) {
|
|
478
|
+
if (this.keyIds[i] === keyId) {
|
|
479
|
+
if (this.objs[i] === UNDEFINED) {
|
|
480
|
+
this.objs[i] = this._new(this._providers[i]);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
return this.objs[i];
|
|
484
|
+
}
|
|
485
|
+
}
|
|
490
486
|
|
|
491
|
-
|
|
492
|
-
_throwOrNull(key: ReflectiveKey, notFoundValue: any): any {
|
|
493
|
-
if (notFoundValue !== THROW_IF_NOT_FOUND) {
|
|
494
|
-
return notFoundValue;
|
|
495
|
-
} else {
|
|
496
|
-
throw noProviderError(this, key);
|
|
487
|
+
return UNDEFINED;
|
|
497
488
|
}
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
/** @internal */
|
|
507
|
-
_getByKeyDefault(key: ReflectiveKey, notFoundValue: any, visibility: SelfAnnotation | SkipSelfAnnotation | null): any {
|
|
508
|
-
let inj: Injector | null;
|
|
509
|
-
|
|
510
|
-
if (visibility instanceof SkipSelfAnnotation) {
|
|
511
|
-
inj = this._parent;
|
|
512
|
-
} else {
|
|
513
|
-
inj = this;
|
|
489
|
+
|
|
490
|
+
/** @internal */
|
|
491
|
+
_throwOrNull(key: ReflectiveKey, notFoundValue: any): any {
|
|
492
|
+
if (notFoundValue !== THROW_IF_NOT_FOUND) {
|
|
493
|
+
return notFoundValue;
|
|
494
|
+
} else {
|
|
495
|
+
throw noProviderError(this, key);
|
|
496
|
+
}
|
|
514
497
|
}
|
|
515
498
|
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
inj = inj_._parent;
|
|
499
|
+
/** @internal */
|
|
500
|
+
_getByKeySelf(key: ReflectiveKey, notFoundValue: any): any {
|
|
501
|
+
const obj = this._getObjByKeyId(key.id);
|
|
502
|
+
return obj !== UNDEFINED ? obj : this._throwOrNull(key, notFoundValue);
|
|
521
503
|
}
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
504
|
+
|
|
505
|
+
/** @internal */
|
|
506
|
+
_getByKeyDefault(key: ReflectiveKey, notFoundValue: any, visibility: SelfAnnotation | SkipSelfAnnotation | null): any {
|
|
507
|
+
let inj: Injector | null;
|
|
508
|
+
|
|
509
|
+
if (visibility instanceof SkipSelfAnnotation) {
|
|
510
|
+
inj = this._parent;
|
|
511
|
+
} else {
|
|
512
|
+
inj = this;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
while (inj instanceof ReflectiveInjector_) {
|
|
516
|
+
const inj_ = <ReflectiveInjector_>inj;
|
|
517
|
+
const obj = inj_._getObjByKeyId(key.id);
|
|
518
|
+
if (obj !== UNDEFINED) return obj;
|
|
519
|
+
inj = inj_._parent;
|
|
520
|
+
}
|
|
521
|
+
if (inj !== null) {
|
|
522
|
+
return inj.get(key.token, notFoundValue);
|
|
523
|
+
} else {
|
|
524
|
+
return this._throwOrNull(key, notFoundValue);
|
|
525
|
+
}
|
|
526
526
|
}
|
|
527
|
-
}
|
|
528
527
|
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
528
|
+
get displayName(): string {
|
|
529
|
+
const providers = _mapProviders(this, (b: ResolvedReflectiveProvider) => ' "' + b.key.displayName + '" ').join(', ');
|
|
530
|
+
return `ReflectiveInjector(providers: [${providers}])`;
|
|
531
|
+
}
|
|
533
532
|
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
533
|
+
toString(): string {
|
|
534
|
+
return this.displayName;
|
|
535
|
+
}
|
|
537
536
|
}
|
|
538
537
|
|
|
539
538
|
const INJECTOR_KEY = ReflectiveKey.get(Injector);
|
|
540
539
|
|
|
541
540
|
function _mapProviders(injector: ReflectiveInjector_, fn: Function): any[] {
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
541
|
+
const res: any[] = new Array(injector._providers.length);
|
|
542
|
+
for (let i = 0; i < injector._providers.length; ++i) {
|
|
543
|
+
res[i] = fn(injector.getProviderAtIndex(i));
|
|
544
|
+
}
|
|
545
|
+
return res;
|
|
547
546
|
}
|