1 | /**
|
2 | * @license
|
3 | * Copyright Google Inc. All Rights Reserved.
|
4 | *
|
5 | * Use of this source code is governed by an MIT-style license that can be
|
6 | * found in the LICENSE file at https://angular.io/license
|
7 | */
|
8 | import { wrappedError } from './facade/errors';
|
9 | import { ERROR_ORIGINAL_ERROR, getOriginalError } from './facade/errors';
|
10 | import { stringify } from './facade/lang';
|
11 | function findFirstClosedCycle(keys) {
|
12 | var res = [];
|
13 | for (var i = 0; i < keys.length; ++i) {
|
14 | if (res.indexOf(keys[i]) > -1) {
|
15 | res.push(keys[i]);
|
16 | return res;
|
17 | }
|
18 | res.push(keys[i]);
|
19 | }
|
20 | return res;
|
21 | }
|
22 | function constructResolvingPath(keys) {
|
23 | if (keys.length > 1) {
|
24 | var reversed = findFirstClosedCycle(keys.slice().reverse());
|
25 | var tokenStrs = reversed.map(function (k) { return stringify(k.token); });
|
26 | return ' (' + tokenStrs.join(' -> ') + ')';
|
27 | }
|
28 | return '';
|
29 | }
|
30 | function injectionError(injector, key, constructResolvingMessage, originalError) {
|
31 | var error = (originalError ? wrappedError('', originalError) : Error());
|
32 | error.addKey = addKey;
|
33 | error.keys = [key];
|
34 | error.injectors = [injector];
|
35 | error.constructResolvingMessage = constructResolvingMessage;
|
36 | error.message = error.constructResolvingMessage();
|
37 | error[ERROR_ORIGINAL_ERROR] = originalError;
|
38 | return error;
|
39 | }
|
40 | function addKey(injector, key) {
|
41 | this.injectors.push(injector);
|
42 | this.keys.push(key);
|
43 | this.message = this.constructResolvingMessage();
|
44 | }
|
45 | /**
|
46 | * Thrown when trying to retrieve a dependency by key from {@link Injector}, but the
|
47 | * {@link Injector} does not have a {@link Provider} for the given key.
|
48 | *
|
49 | * ### Example ([live demo](http://plnkr.co/edit/vq8D3FRB9aGbnWJqtEPE?p=preview))
|
50 | *
|
51 | * ```typescript
|
52 | * class A {
|
53 | * constructor(b:B) {}
|
54 | * }
|
55 | *
|
56 | * expect(() => Injector.resolveAndCreate([A])).toThrowError();
|
57 | * ```
|
58 | */
|
59 | export function noProviderError(injector, key) {
|
60 | return injectionError(injector, key, function () {
|
61 | var first = stringify(this.keys[0].token);
|
62 | return "No provider for " + first + "!" + constructResolvingPath(this.keys);
|
63 | });
|
64 | }
|
65 | /**
|
66 | * Thrown when dependencies form a cycle.
|
67 | *
|
68 | * ### Example ([live demo](http://plnkr.co/edit/wYQdNos0Tzql3ei1EV9j?p=info))
|
69 | *
|
70 | * ```typescript
|
71 | * var injector = Injector.resolveAndCreate([
|
72 | * {provide: "one", useFactory: (two) => "two", deps: [[new Inject("two")]]},
|
73 | * {provide: "two", useFactory: (one) => "one", deps: [[new Inject("one")]]}
|
74 | * ]);
|
75 | *
|
76 | * expect(() => injector.get("one")).toThrowError();
|
77 | * ```
|
78 | *
|
79 | * Retrieving `A` or `B` throws a `CyclicDependencyError` as the graph above cannot be constructed.
|
80 | */
|
81 | export function cyclicDependencyError(injector, key) {
|
82 | return injectionError(injector, key, function () {
|
83 | return "Cannot instantiate cyclic dependency!" + constructResolvingPath(this.keys);
|
84 | });
|
85 | }
|
86 | /**
|
87 | * Thrown when a constructing type returns with an Error.
|
88 | *
|
89 | * The `InstantiationError` class contains the original error plus the dependency graph which caused
|
90 | * this object to be instantiated.
|
91 | *
|
92 | * ### Example ([live demo](http://plnkr.co/edit/7aWYdcqTQsP0eNqEdUAf?p=preview))
|
93 | *
|
94 | * ```typescript
|
95 | * class A {
|
96 | * constructor() {
|
97 | * throw new Error('message');
|
98 | * }
|
99 | * }
|
100 | *
|
101 | * var injector = Injector.resolveAndCreate([A]);
|
102 |
|
103 | * try {
|
104 | * injector.get(A);
|
105 | * } catch (e) {
|
106 | * expect(e instanceof InstantiationError).toBe(true);
|
107 | * expect(e.originalException.message).toEqual("message");
|
108 | * expect(e.originalStack).toBeDefined();
|
109 | * }
|
110 | * ```
|
111 | */
|
112 | export function instantiationError(injector, originalException, originalStack, key) {
|
113 | return injectionError(injector, key, function () {
|
114 | var first = stringify(this.keys[0].token);
|
115 | return getOriginalError(this).message + ": Error during instantiation of " + first + "!" + constructResolvingPath(this.keys) + ".";
|
116 | }, originalException);
|
117 | }
|
118 | /**
|
119 | * Thrown when an object other then {@link Provider} (or `Type`) is passed to {@link Injector}
|
120 | * creation.
|
121 | *
|
122 | * ### Example ([live demo](http://plnkr.co/edit/YatCFbPAMCL0JSSQ4mvH?p=preview))
|
123 | *
|
124 | * ```typescript
|
125 | * expect(() => Injector.resolveAndCreate(["not a type"])).toThrowError();
|
126 | * ```
|
127 | */
|
128 | export function invalidProviderError(provider) {
|
129 | return Error("Invalid provider - only instances of Provider and Type are allowed, got: " + provider);
|
130 | }
|
131 | /**
|
132 | * Thrown when the class has no annotation information.
|
133 | *
|
134 | * Lack of annotation information prevents the {@link Injector} from determining which dependencies
|
135 | * need to be injected into the constructor.
|
136 | *
|
137 | * ### Example ([live demo](http://plnkr.co/edit/rHnZtlNS7vJOPQ6pcVkm?p=preview))
|
138 | *
|
139 | * ```typescript
|
140 | * class A {
|
141 | * constructor(b) {}
|
142 | * }
|
143 | *
|
144 | * expect(() => Injector.resolveAndCreate([A])).toThrowError();
|
145 | * ```
|
146 | *
|
147 | * This error is also thrown when the class not marked with {@link Injectable} has parameter types.
|
148 | *
|
149 | * ```typescript
|
150 | * class B {}
|
151 | *
|
152 | * class A {
|
153 | * constructor(b:B) {} // no information about the parameter types of A is available at runtime.
|
154 | * }
|
155 | *
|
156 | * expect(() => Injector.resolveAndCreate([A,B])).toThrowError();
|
157 | * ```
|
158 | * @stable
|
159 | */
|
160 | export function noAnnotationError(typeOrFunc, params) {
|
161 | var signature = [];
|
162 | for (var i = 0, ii = params.length; i < ii; i++) {
|
163 | var parameter = params[i];
|
164 | if (!parameter || parameter.length === 0) {
|
165 | signature.push('?');
|
166 | }
|
167 | else {
|
168 | signature.push(parameter.map(stringify).join(' '));
|
169 | }
|
170 | }
|
171 | return Error("Cannot resolve all parameters for '" +
|
172 | stringify(typeOrFunc) +
|
173 | "'(" +
|
174 | signature.join(', ') +
|
175 | '). ' +
|
176 | "Make sure that all the parameters are decorated with Inject or have valid type annotations and that '" +
|
177 | stringify(typeOrFunc) +
|
178 | "' is decorated with Injectable.");
|
179 | }
|
180 | /**
|
181 | * Thrown when getting an object by index.
|
182 | *
|
183 | * ### Example ([live demo](http://plnkr.co/edit/bRs0SX2OTQiJzqvjgl8P?p=preview))
|
184 | *
|
185 | * ```typescript
|
186 | * class A {}
|
187 | *
|
188 | * var injector = Injector.resolveAndCreate([A]);
|
189 | *
|
190 | * expect(() => injector.getAt(100)).toThrowError();
|
191 | * ```
|
192 | * @stable
|
193 | */
|
194 | export function outOfBoundsError(index) {
|
195 | return Error("Index " + index + " is out-of-bounds.");
|
196 | }
|
197 | // TODO: add a working example after alpha38 is released
|
198 | /**
|
199 | * Thrown when a multi provider and a regular provider are bound to the same token.
|
200 | *
|
201 | * ### Example
|
202 | *
|
203 | * ```typescript
|
204 | * expect(() => Injector.resolveAndCreate([
|
205 | * { provide: "Strings", useValue: "string1", multi: true},
|
206 | * { provide: "Strings", useValue: "string2", multi: false}
|
207 | * ])).toThrowError();
|
208 | * ```
|
209 | */
|
210 | export function mixingMultiProvidersWithRegularProvidersError(provider1, provider2) {
|
211 | return Error("Cannot mix multi providers and regular providers, got: " + provider1 + " " + provider2);
|
212 | }
|
213 | //# sourceMappingURL=reflective_errors.js.map |
\ | No newline at end of file |