Skip to content

Commit ec2d8cc

Browse files
committed
feat(binding): throw on binding to a blank alias
fixes angular#2068
1 parent 05d66bb commit ec2d8cc

File tree

2 files changed

+52
-43
lines changed

2 files changed

+52
-43
lines changed

modules/angular2/src/di/binding.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {Type, isBlank, isPresent, CONST} from 'angular2/src/facade/lang';
1+
import {Type, isBlank, isPresent, CONST, BaseException, stringify} from 'angular2/src/facade/lang';
22
import {List, MapWrapper, ListWrapper} from 'angular2/src/facade/collection';
33
import {reflector} from 'angular2/src/reflection/reflection';
44
import {Key} from './key';
@@ -383,7 +383,12 @@ export class BindingBuilder {
383383
* expect(injectorClass.get(Vehicle) instanceof Car).toBe(true);
384384
* ```
385385
*/
386-
toAlias(aliasToken): Binding { return new Binding(this.token, {toAlias: aliasToken}); }
386+
toAlias(aliasToken): Binding {
387+
if (isBlank(aliasToken)) {
388+
throw new BaseException(`Can not alias ${stringify(this.token)} to a blank value!`);
389+
}
390+
return new Binding(this.token, {toAlias: aliasToken});
391+
}
387392

388393
/**
389394
* Binds a key to a function which computes the value.

modules/angular2/test/di/injector_spec.ts

Lines changed: 45 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -79,38 +79,38 @@ class NoAnnotations {
7979
}
8080

8181
export function main() {
82-
describe('injector', function() {
82+
describe('injector', () => {
8383

84-
it('should instantiate a class without dependencies', function() {
84+
it('should instantiate a class without dependencies', () => {
8585
var injector = Injector.resolveAndCreate([Engine]);
8686
var engine = injector.get(Engine);
8787

8888
expect(engine).toBeAnInstanceOf(Engine);
8989
});
9090

91-
it('should resolve dependencies based on type information', function() {
91+
it('should resolve dependencies based on type information', () => {
9292
var injector = Injector.resolveAndCreate([Engine, Car]);
9393
var car = injector.get(Car);
9494

9595
expect(car).toBeAnInstanceOf(Car);
9696
expect(car.engine).toBeAnInstanceOf(Engine);
9797
});
9898

99-
it('should resolve dependencies based on @Inject annotation', function() {
99+
it('should resolve dependencies based on @Inject annotation', () => {
100100
var injector = Injector.resolveAndCreate([TurboEngine, Engine, CarWithInject]);
101101
var car = injector.get(CarWithInject);
102102

103103
expect(car).toBeAnInstanceOf(CarWithInject);
104104
expect(car.engine).toBeAnInstanceOf(TurboEngine);
105105
});
106106

107-
it('should throw when no type and not @Inject', function() {
107+
it('should throw when no type and not @Inject', () => {
108108
expect(() => Injector.resolveAndCreate([NoAnnotations]))
109109
.toThrowError('Cannot resolve all parameters for NoAnnotations. ' +
110110
'Make sure they all have valid type or annotations.');
111111
});
112112

113-
it('should cache instances', function() {
113+
it('should cache instances', () => {
114114
var injector = Injector.resolveAndCreate([Engine]);
115115

116116
var e1 = injector.get(Engine);
@@ -119,14 +119,14 @@ export function main() {
119119
expect(e1).toBe(e2);
120120
});
121121

122-
it('should bind to a value', function() {
122+
it('should bind to a value', () => {
123123
var injector = Injector.resolveAndCreate([bind(Engine).toValue("fake engine")]);
124124

125125
var engine = injector.get(Engine);
126126
expect(engine).toEqual("fake engine");
127127
});
128128

129-
it('should bind to a factory', function() {
129+
it('should bind to a factory', () => {
130130
function sportsCarFactory(e) { return new SportsCar(e); }
131131

132132
var injector =
@@ -137,7 +137,7 @@ export function main() {
137137
expect(car.engine).toBeAnInstanceOf(Engine);
138138
});
139139

140-
it('should bind to an alias', function() {
140+
it('should bind to an alias', () => {
141141
var injector = Injector.resolveAndCreate(
142142
[Engine, bind(SportsCar).toClass(SportsCar), bind(Car).toAlias(SportsCar)]);
143143

@@ -147,13 +147,17 @@ export function main() {
147147
expect(car).toBe(sportsCar);
148148
});
149149

150-
it('should throw when the aliased binding does not exist', function() {
150+
it('should throw when the aliased binding does not exist', () => {
151151
var injector = Injector.resolveAndCreate([bind('car').toAlias(SportsCar)]);
152152
var e = `No provider for ${stringify(SportsCar)}! (car -> ${stringify(SportsCar)})`;
153153
expect(() => injector.get('car')).toThrowError(e);
154154
});
155155

156-
it('should handle forwardRef in toAlias', function() {
156+
it('should throw with a meaningful message when the aliased binding is blank', () => {
157+
expect(() => bind('car').toAlias(null)).toThrowError('Can not alias car to a blank value!');
158+
});
159+
160+
it('should handle forwardRef in toAlias', () => {
157161
var injector = Injector.resolveAndCreate([
158162
bind('originalEngine')
159163
.toClass(forwardRef(() => Engine)),
@@ -162,7 +166,7 @@ export function main() {
162166
expect(injector.get('aliasedEngine')).toBeAnInstanceOf(Engine);
163167
});
164168

165-
it('should support overriding factory dependencies', function() {
169+
it('should support overriding factory dependencies', () => {
166170
var injector =
167171
Injector
168172
.resolveAndCreate([Engine, bind(Car).toFactory((e) => new SportsCar(e), [Engine])]);
@@ -172,35 +176,35 @@ export function main() {
172176
expect(car.engine).toBeAnInstanceOf(Engine);
173177
});
174178

175-
it('should support optional dependencies', function() {
179+
it('should support optional dependencies', () => {
176180
var injector = Injector.resolveAndCreate([CarWithOptionalEngine]);
177181

178182
var car = injector.get(CarWithOptionalEngine);
179183
expect(car.engine).toEqual(null);
180184
});
181185

182-
it("should flatten passed-in bindings", function() {
186+
it("should flatten passed-in bindings", () => {
183187
var injector = Injector.resolveAndCreate([[[Engine, Car]]]);
184188

185189
var car = injector.get(Car);
186190
expect(car).toBeAnInstanceOf(Car);
187191
});
188192

189-
it("should use the last binding " + "when there are multiple bindings for same token",
190-
function() {
191-
var injector = Injector.resolveAndCreate(
192-
[bind(Engine).toClass(Engine), bind(Engine).toClass(TurboEngine)]);
193+
it("should use the last binding when there are multiple bindings for same token", () => {
194+
var injector =
195+
Injector
196+
.resolveAndCreate([bind(Engine).toClass(Engine), bind(Engine).toClass(TurboEngine)]);
193197

194-
expect(injector.get(Engine)).toBeAnInstanceOf(TurboEngine);
195-
});
198+
expect(injector.get(Engine)).toBeAnInstanceOf(TurboEngine);
199+
});
196200

197-
it('should use non-type tokens', function() {
201+
it('should use non-type tokens', () => {
198202
var injector = Injector.resolveAndCreate([bind('token').toValue('value')]);
199203

200204
expect(injector.get('token')).toEqual('value');
201205
});
202206

203-
it('should throw when given invalid bindings', function() {
207+
it('should throw when given invalid bindings', () => {
204208
expect(() => Injector.resolveAndCreate(<any>["blah"]))
205209
.toThrowError(
206210
'Invalid binding - only instances of Binding and Type are allowed, got: blah');
@@ -209,26 +213,26 @@ export function main() {
209213
'got: blah');
210214
});
211215

212-
it('should provide itself', function() {
216+
it('should provide itself', () => {
213217
var parent = Injector.resolveAndCreate([]);
214218
var child = parent.resolveAndCreateChild([]);
215219

216220
expect(child.get(Injector)).toBe(child);
217221
});
218222

219-
it('should throw when no provider defined', function() {
223+
it('should throw when no provider defined', () => {
220224
var injector = Injector.resolveAndCreate([]);
221225
expect(() => injector.get('NonExisting')).toThrowError('No provider for NonExisting!');
222226
});
223227

224-
it('should show the full path when no provider', function() {
228+
it('should show the full path when no provider', () => {
225229
var injector = Injector.resolveAndCreate([CarWithDashboard, Engine, Dashboard]);
226230
expect(() => injector.get(CarWithDashboard))
227231
.toThrowError(
228232
`No provider for DashboardSoftware! (${stringify(CarWithDashboard)} -> ${stringify(Dashboard)} -> DashboardSoftware)`);
229233
});
230234

231-
it('should throw when trying to instantiate a cyclic dependency', function() {
235+
it('should throw when trying to instantiate a cyclic dependency', () => {
232236
var injector = Injector.resolveAndCreate([Car, bind(Engine).toClass(CyclicEngine)]);
233237

234238
expect(() => injector.get(Car))
@@ -240,7 +244,7 @@ export function main() {
240244
`Cannot instantiate cyclic dependency! (${stringify(Car)} -> ${stringify(Engine)} -> ${stringify(Car)})`);
241245
});
242246

243-
it('should show the full path when error happens in a constructor', function() {
247+
it('should show the full path when error happens in a constructor', () => {
244248
var injector = Injector.resolveAndCreate([Car, bind(Engine).toClass(BrokenEngine)]);
245249

246250
try {
@@ -254,7 +258,7 @@ export function main() {
254258
}
255259
});
256260

257-
it('should instantiate an object after a failed attempt', function() {
261+
it('should instantiate an object after a failed attempt', () => {
258262
var isBroken = true;
259263

260264
var injector = Injector.resolveAndCreate(
@@ -272,16 +276,16 @@ export function main() {
272276
expect(injector.get('null')).toBe(null);
273277
});
274278

275-
describe("default bindings", function() {
276-
it("should be used when no matching binding found", function() {
279+
describe("default bindings", () => {
280+
it("should be used when no matching binding found", () => {
277281
var injector = Injector.resolveAndCreate([], { defaultBindings: true });
278282

279283
var car = injector.get(Car);
280284

281285
expect(car).toBeAnInstanceOf(Car);
282286
});
283287

284-
it("should use the matching binding when it is available", function() {
288+
it("should use the matching binding when it is available", () => {
285289
var injector =
286290
Injector.resolveAndCreate([bind(Car).toClass(SportsCar)], {defaultBindings: true});
287291

@@ -291,8 +295,8 @@ export function main() {
291295
});
292296
});
293297

294-
describe("child", function() {
295-
it('should load instances from parent injector', function() {
298+
describe("child", () => {
299+
it('should load instances from parent injector', () => {
296300
var parent = Injector.resolveAndCreate([Engine]);
297301
var child = parent.resolveAndCreateChild([]);
298302

@@ -303,15 +307,15 @@ export function main() {
303307
});
304308

305309
it("should not use the child bindings when resolving the dependencies of a parent binding",
306-
function() {
310+
() => {
307311
var parent = Injector.resolveAndCreate([Car, Engine]);
308312
var child = parent.resolveAndCreateChild([bind(Engine).toClass(TurboEngine)]);
309313

310314
var carFromChild = child.get(Car);
311315
expect(carFromChild.engine).toBeAnInstanceOf(Engine);
312316
});
313317

314-
it('should create new instance in a child injector', function() {
318+
it('should create new instance in a child injector', () => {
315319
var parent = Injector.resolveAndCreate([Engine]);
316320
var child = parent.resolveAndCreateChild([bind(Engine).toClass(TurboEngine)]);
317321

@@ -322,7 +326,7 @@ export function main() {
322326
expect(engineFromChild).toBeAnInstanceOf(TurboEngine);
323327
});
324328

325-
it("should create child injectors without default bindings", function() {
329+
it("should create child injectors without default bindings", () => {
326330
var parent = Injector.resolveAndCreate([], { defaultBindings: true });
327331
var child = parent.resolveAndCreateChild([]);
328332

@@ -340,15 +344,15 @@ export function main() {
340344
});
341345
});
342346

343-
describe("lazy", function() {
344-
it("should create dependencies lazily", function() {
347+
describe("lazy", () => {
348+
it("should create dependencies lazily", () => {
345349
var injector = Injector.resolveAndCreate([Engine, CarWithLazyEngine]);
346350

347351
var car = injector.get(CarWithLazyEngine);
348352
expect(car.engineFactory()).toBeAnInstanceOf(Engine);
349353
});
350354

351-
it("should cache instance created lazily", function() {
355+
it("should cache instance created lazily", () => {
352356
var injector = Injector.resolveAndCreate([Engine, CarWithLazyEngine]);
353357

354358
var car = injector.get(CarWithLazyEngine);
@@ -359,7 +363,7 @@ export function main() {
359363
});
360364
});
361365

362-
describe('resolve', function() {
366+
describe('resolve', () => {
363367
it('should resolve and flatten', () => {
364368
var bindings = Injector.resolve([Engine, [BrokenEngine]]);
365369
bindings.forEach(function(b) {
@@ -388,7 +392,7 @@ export function main() {
388392
expect(dashboardSoftwareBinding.dependencies[0].key).toEqual(Key.get(BrokenEngine));
389393
});
390394

391-
it('should support overriding factory dependencies with dependency annotations', function() {
395+
it('should support overriding factory dependencies with dependency annotations', () => {
392396
var bindings = Injector.resolve(
393397
[bind("token")
394398
.toFactory((e) => "result",

0 commit comments

Comments
 (0)