xterm
[VSoRC/.git] / node_modules / xterm / src / common / services / InstantiationService.ts
1 /**
2  * Copyright (c) 2019 The xterm.js authors. All rights reserved.
3  * @license MIT
4  *
5  * This was heavily inspired from microsoft/vscode's dependency injection system (MIT).
6  */
7 /*---------------------------------------------------------------------------------------------
8  *  Copyright (c) Microsoft Corporation. All rights reserved.
9  *  Licensed under the MIT License. See License.txt in the project root for license information.
10  *--------------------------------------------------------------------------------------------*/
11
12 import { IInstantiationService, IServiceIdentifier } from 'common/services/Services';
13 import { getServiceDependencies } from 'common/services/ServiceRegistry';
14
15 export class ServiceCollection {
16
17   private _entries = new Map<IServiceIdentifier<any>, any>();
18
19   constructor(...entries: [IServiceIdentifier<any>, any][]) {
20     for (const [id, service] of entries) {
21       this.set(id, service);
22     }
23   }
24
25   set<T>(id: IServiceIdentifier<T>, instance: T): T {
26     const result = this._entries.get(id);
27     this._entries.set(id, instance);
28     return result;
29   }
30
31   forEach(callback: (id: IServiceIdentifier<any>, instance: any) => any): void {
32     this._entries.forEach((value, key) => callback(key, value));
33   }
34
35   has(id: IServiceIdentifier<any>): boolean {
36     return this._entries.has(id);
37   }
38
39   get<T>(id: IServiceIdentifier<T>): T {
40     return this._entries.get(id);
41   }
42 }
43
44 export class InstantiationService implements IInstantiationService {
45   private readonly _services: ServiceCollection = new ServiceCollection();
46
47   constructor() {
48     this._services.set(IInstantiationService, this);
49   }
50
51   public setService<T>(id: IServiceIdentifier<T>, instance: T): void {
52     this._services.set(id, instance);
53   }
54
55   public createInstance<T>(ctor: any, ...args: any[]): any {
56     const serviceDependencies = getServiceDependencies(ctor).sort((a, b) => a.index - b.index);
57
58     const serviceArgs: any[] = [];
59     for (const dependency of serviceDependencies) {
60       const service = this._services.get(dependency.id);
61       if (!service) {
62         throw new Error(`[createInstance] ${ctor.name} depends on UNKNOWN service ${dependency.id}.`);
63       }
64       serviceArgs.push(service);
65     }
66
67     const firstServiceArgPos = serviceDependencies.length > 0 ? serviceDependencies[0].index : args.length;
68
69     // check for argument mismatches, adjust static args if needed
70     if (args.length !== firstServiceArgPos) {
71       throw new Error(`[createInstance] First service dependency of ${ctor.name} at position ${firstServiceArgPos + 1} conflicts with ${args.length} static arguments`);
72     }
73
74     // now create the instance
75     return <T>new ctor(...[...args, ...serviceArgs]);
76   }
77 }