199
200
private _safeCreateAndCacheServiceInstance<T>(id: ServiceIdentifier<T>, desc: SyncDescriptor<T>, _trace: Trace): T {
202
throw new Error(`illegal state - RECURSIVELY instantiating service '${id}'`);
203
}
205
>
try {
206
>
return this._createAndCacheServiceInstance(id, desc, _trace);
207
>
} finally {
208
>
this._activeInstantiations.delete(id);
209
>
}
210
>
}
211
212
private _createAndCacheServiceInstance<T>(id: ServiceIdentifier<T>, desc: SyncDescriptor<T>, _trace: Trace): T {
214
>
type Triple = { id: ServiceIdentifier<any>; desc: SyncDescriptor<any>; _trace: Trace };
215
>
const graph = new Graph<Triple>(data => data.id.toString());
216
>
217
>
let cycleCount = 0;
218
>
const stack = [{ id, desc, _trace }];
219
>
const seen = new Set<string>();
220
>
while (stack.length) {
221
>
const item = stack.pop()!;
222
>
223
>
if (seen.has(String(item.id))) {
224
continue;
225
}
227
>
228
>
graph.lookupOrInsertNode(item);
229
>
230
>
// a weak but working heuristic for cycle checks
231
>
if (cycleCount++ > 1000) {
232
throw new CyclicDependencyError(graph);
233
}
235
>
// check all dependencies for existence and if they need to be created first
236
>
for (const dependency of _util.getServiceDependencies(item.desc.ctor)) {
237
238
const instanceOrDesc = this._getServiceInstanceOrDescriptor(dependency.id);