build: reformat repo to new clang@1.4.0 (#36628)

PR Close #36628
This commit is contained in:
Joey Perrott
2020-04-13 17:43:52 -07:00
committed by atscott
parent 4b3f9ac739
commit 26f49151e7
1163 changed files with 31727 additions and 24036 deletions

View File

@ -22,7 +22,8 @@ import {describe, expect, it} from '@angular/core/testing/src/testing_internal';
.toThrowError('NullInjectorError: No provider for someToken!');
});
it('should return the default value',
() => { expect(Injector.NULL.get('someToken', 'notFound')).toEqual('notFound'); });
it('should return the default value', () => {
expect(Injector.NULL.get('someToken', 'notFound')).toEqual('notFound');
});
});
}

View File

@ -6,8 +6,8 @@
* found in the LICENSE file at https://angular.io/license
*/
import {INJECTOR, InjectFlags, InjectionToken, Injector, Optional, ɵɵdefineInjectable, ɵɵdefineInjector, ɵɵinject} from '@angular/core';
import {R3Injector, createInjector} from '@angular/core/src/di/r3_injector';
import {InjectFlags, InjectionToken, INJECTOR, Injector, Optional, ɵɵdefineInjectable, ɵɵdefineInjector, ɵɵinject} from '@angular/core';
import {createInjector, R3Injector} from '@angular/core/src/di/r3_injector';
import {expect} from '@angular/platform-browser/testing/src/matchers';
describe('InjectorDef-based createInjector()', () => {
@ -64,7 +64,7 @@ describe('InjectorDef-based createInjector()', () => {
providedIn: null,
// ChildService is derived from ServiceWithDep, so the factory function here must do the right
// thing and create an instance of the requested type if one is given.
factory: (t?: typeof ServiceWithDep) => new (t || ServiceWithDep)(ɵɵinject(Service)),
factory: (t?: typeof ServiceWithDep) => new(t || ServiceWithDep)(ɵɵinject(Service)),
});
}
@ -114,7 +114,9 @@ describe('InjectorDef-based createInjector()', () => {
factory: () => new DeepService(),
});
ngOnDestroy(): void { deepServiceDestroyed = true; }
ngOnDestroy(): void {
deepServiceDestroyed = true;
}
}
let eagerServiceCreated: boolean = false;
@ -125,20 +127,31 @@ describe('InjectorDef-based createInjector()', () => {
factory: () => new EagerService(),
});
constructor() { eagerServiceCreated = true; }
constructor() {
eagerServiceCreated = true;
}
}
let deepModuleCreated: boolean = false;
class DeepModule {
constructor(eagerService: EagerService) { deepModuleCreated = true; }
constructor(eagerService: EagerService) {
deepModuleCreated = true;
}
static ɵinj = ɵɵdefineInjector({
factory: () => new DeepModule(ɵɵinject(EagerService)),
imports: undefined,
providers: [
EagerService,
{provide: DeepService, useFactory: () => { throw new Error('Not overridden!'); }},
],
providers:
[
EagerService,
{
provide: DeepService,
useFactory:
() => {
throw new Error('Not overridden!');
}
},
],
});
static safe() {
@ -171,22 +184,23 @@ describe('InjectorDef-based createInjector()', () => {
static ɵinj = ɵɵdefineInjector({
factory: () => new Module(),
imports: [IntermediateModule],
providers: [
ChildService,
ServiceWithDep,
ServiceWithOptionalDep,
ServiceWithMultiDep,
{provide: LOCALE, multi: true, useValue: 'en'},
{provide: LOCALE, multi: true, useValue: 'es'},
{provide: PRIMITIVE_VALUE, useValue: 'foo'},
{provide: UNDEFINED_VALUE, useValue: undefined},
Service,
{provide: SERVICE_TOKEN, useExisting: Service},
CircularA,
CircularB,
{provide: STATIC_TOKEN, useClass: StaticService, deps: [Service]},
InjectorWithDep,
],
providers:
[
ChildService,
ServiceWithDep,
ServiceWithOptionalDep,
ServiceWithMultiDep,
{provide: LOCALE, multi: true, useValue: 'en'},
{provide: LOCALE, multi: true, useValue: 'es'},
{provide: PRIMITIVE_VALUE, useValue: 'foo'},
{provide: UNDEFINED_VALUE, useValue: undefined},
Service,
{provide: SERVICE_TOKEN, useExisting: Service},
CircularA,
CircularB,
{provide: STATIC_TOKEN, useClass: StaticService, deps: [Service]},
InjectorWithDep,
],
});
}
@ -224,7 +238,9 @@ describe('InjectorDef-based createInjector()', () => {
factory: () => new ScopedService(),
});
ngOnDestroy(): void { scopedServiceDestroyed = true; }
ngOnDestroy(): void {
scopedServiceDestroyed = true;
}
}
class WrongScopeService {
@ -252,10 +268,11 @@ describe('InjectorDef-based createInjector()', () => {
class WithProvidersTest {
static ɵinj = ɵɵdefineInjector({
factory: () => new WithProvidersTest(),
imports: [
{ngModule: MultiProviderA, providers: [{provide: LOCALE, multi: true, useValue: 'C'}]},
MultiProviderB
],
imports:
[
{ngModule: MultiProviderA, providers: [{provide: LOCALE, multi: true, useValue: 'C'}]},
MultiProviderB
],
providers: [],
});
}
@ -276,7 +293,9 @@ describe('InjectorDef-based createInjector()', () => {
imports: undefined,
providers: [],
});
constructor() { moduleRegistrations.push('ChildModule'); }
constructor() {
moduleRegistrations.push('ChildModule');
}
}
class RootModule {
@ -285,7 +304,9 @@ describe('InjectorDef-based createInjector()', () => {
imports: [ChildModule],
providers: [],
});
constructor() { moduleRegistrations.push('RootModule'); }
constructor() {
moduleRegistrations.push('RootModule');
}
}
createInjector(RootModule);
expect(moduleRegistrations).toEqual(['ChildModule', 'RootModule']);
@ -297,8 +318,9 @@ describe('InjectorDef-based createInjector()', () => {
expect(injector.get(Service)).toBe(instance);
});
it('returns the default value if a provider isn\'t present',
() => { expect(injector.get(ServiceTwo, null)).toBeNull(); });
it('returns the default value if a provider isn\'t present', () => {
expect(injector.get(ServiceTwo, null)).toBeNull();
});
it('should throw when no provider defined', () => {
expect(() => injector.get(ServiceTwo))
@ -373,14 +395,17 @@ describe('InjectorDef-based createInjector()', () => {
expect(instance.dep).toBe(injector.get(Service));
});
it('allows injecting itself via INJECTOR',
() => { expect(injector.get(INJECTOR)).toBe(injector); });
it('allows injecting itself via INJECTOR', () => {
expect(injector.get(INJECTOR)).toBe(injector);
});
it('allows injecting itself via Injector',
() => { expect(injector.get(Injector)).toBe(injector); });
it('allows injecting itself via Injector', () => {
expect(injector.get(Injector)).toBe(injector);
});
it('allows injecting a deeply imported service',
() => { expect(injector.get(DeepService) instanceof DeepService).toBeTruthy(); });
it('allows injecting a deeply imported service', () => {
expect(injector.get(DeepService) instanceof DeepService).toBeTruthy();
});
it('allows injecting a scoped service', () => {
const instance = injector.get(ScopedService);
@ -393,8 +418,9 @@ describe('InjectorDef-based createInjector()', () => {
expect(instance instanceof ChildService).toBe(true);
});
it('does not create instances of a service not in scope',
() => { expect(injector.get(WrongScopeService, null)).toBeNull(); });
it('does not create instances of a service not in scope', () => {
expect(injector.get(WrongScopeService, null)).toBeNull();
});
it('eagerly instantiates the injectordef types', () => {
expect(deepModuleCreated).toBe(true, 'DeepModule not instantiated');
@ -432,11 +458,13 @@ describe('InjectorDef-based createInjector()', () => {
});
describe('error handling', () => {
it('throws an error when a token is not found',
() => { expect(() => injector.get(ServiceTwo)).toThrow(); });
it('throws an error when a token is not found', () => {
expect(() => injector.get(ServiceTwo)).toThrow();
});
it('throws an error on circular deps',
() => { expect(() => injector.get(CircularA)).toThrow(); });
it('throws an error on circular deps', () => {
expect(() => injector.get(CircularA)).toThrow();
});
it('should throw when it can\'t resolve all arguments', () => {
class MissingArgumentType {

View File

@ -6,17 +6,20 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Inject, Injectable, InjectionToken, Injector, Optional, Provider, ReflectiveInjector, ReflectiveKey, Self, forwardRef} from '@angular/core';
import {forwardRef, Inject, Injectable, InjectionToken, Injector, Optional, Provider, ReflectiveInjector, ReflectiveKey, Self} from '@angular/core';
import {ReflectiveInjector_} from '@angular/core/src/di/reflective_injector';
import {ResolvedReflectiveProvider_} from '@angular/core/src/di/reflective_provider';
import {getOriginalError} from '@angular/core/src/errors';
import {expect} from '@angular/platform-browser/testing/src/matchers';
import {stringify} from '../../src/util/stringify';
class Engine {}
class BrokenEngine {
constructor() { throw new Error('Broken Engine'); }
constructor() {
throw new Error('Broken Engine');
}
}
class DashboardSoftware {}
@ -66,464 +69,456 @@ class NoAnnotations {
constructor(secretDependency: any) {}
}
function factoryFn(a: any){}
function factoryFn(a: any) {}
(function() {
const dynamicProviders = [
{provide: 'provider0', useValue: 1}, {provide: 'provider1', useValue: 1},
{provide: 'provider2', useValue: 1}, {provide: 'provider3', useValue: 1},
{provide: 'provider4', useValue: 1}, {provide: 'provider5', useValue: 1},
{provide: 'provider6', useValue: 1}, {provide: 'provider7', useValue: 1},
{provide: 'provider8', useValue: 1}, {provide: 'provider9', useValue: 1},
{provide: 'provider10', useValue: 1}
];
const dynamicProviders = [
{provide: 'provider0', useValue: 1}, {provide: 'provider1', useValue: 1},
{provide: 'provider2', useValue: 1}, {provide: 'provider3', useValue: 1},
{provide: 'provider4', useValue: 1}, {provide: 'provider5', useValue: 1},
{provide: 'provider6', useValue: 1}, {provide: 'provider7', useValue: 1},
{provide: 'provider8', useValue: 1}, {provide: 'provider9', useValue: 1},
{provide: 'provider10', useValue: 1}
];
function createInjector(
providers: Provider[], parent?: ReflectiveInjector | null): ReflectiveInjector_ {
const resolvedProviders = ReflectiveInjector.resolve(providers.concat(dynamicProviders));
if (parent != null) {
return <ReflectiveInjector_>parent.createChildFromResolved(resolvedProviders);
} else {
return <ReflectiveInjector_>ReflectiveInjector.fromResolvedProviders(resolvedProviders);
}
function createInjector(
providers: Provider[], parent?: ReflectiveInjector|null): ReflectiveInjector_ {
const resolvedProviders = ReflectiveInjector.resolve(providers.concat(dynamicProviders));
if (parent != null) {
return <ReflectiveInjector_>parent.createChildFromResolved(resolvedProviders);
} else {
return <ReflectiveInjector_>ReflectiveInjector.fromResolvedProviders(resolvedProviders);
}
}
describe(`injector`, () => {
it('should instantiate a class without dependencies', () => {
const injector = createInjector([Engine]);
const engine = injector.get(Engine);
expect(engine).toBeAnInstanceOf(Engine);
});
it('should resolve dependencies based on type information', () => {
const injector = createInjector([Engine, Car]);
const car = injector.get(Car);
expect(car).toBeAnInstanceOf(Car);
expect(car.engine).toBeAnInstanceOf(Engine);
});
it('should resolve dependencies based on @Inject annotation', () => {
const injector = createInjector([TurboEngine, Engine, CarWithInject]);
const car = injector.get(CarWithInject);
expect(car).toBeAnInstanceOf(CarWithInject);
expect(car.engine).toBeAnInstanceOf(TurboEngine);
});
it('should throw when no type and not @Inject (class case)', () => {
expect(() => createInjector([NoAnnotations]))
.toThrowError(
'Cannot resolve all parameters for \'NoAnnotations\'(?). ' +
'Make sure that all the parameters are decorated with Inject or have valid type annotations ' +
'and that \'NoAnnotations\' is decorated with Injectable.');
});
it('should throw when no type and not @Inject (factory case)', () => {
expect(() => createInjector([{provide: 'someToken', useFactory: factoryFn}]))
.toThrowError(
'Cannot resolve all parameters for \'factoryFn\'(?). ' +
'Make sure that all the parameters are decorated with Inject or have valid type annotations ' +
'and that \'factoryFn\' is decorated with Injectable.');
});
it('should cache instances', () => {
const injector = createInjector([Engine]);
const e1 = injector.get(Engine);
const e2 = injector.get(Engine);
expect(e1).toBe(e2);
});
it('should provide to a value', () => {
const injector = createInjector([{provide: Engine, useValue: 'fake engine'}]);
const engine = injector.get(Engine);
expect(engine).toEqual('fake engine');
});
it('should inject dependencies instance of InjectionToken', () => {
const TOKEN = new InjectionToken<string>('token');
const injector = createInjector([
{provide: TOKEN, useValue: 'by token'},
{provide: Engine, useFactory: (v: string) => v, deps: [[TOKEN]]},
]);
const engine = injector.get(Engine);
expect(engine).toEqual('by token');
});
it('should provide to a factory', () => {
function sportsCarFactory(e: any) { return new SportsCar(e); }
const injector =
createInjector([Engine, {provide: Car, useFactory: sportsCarFactory, deps: [Engine]}]);
const car = injector.get(Car);
expect(car).toBeAnInstanceOf(SportsCar);
expect(car.engine).toBeAnInstanceOf(Engine);
});
it('should supporting provider to null', () => {
const injector = createInjector([{provide: Engine, useValue: null}]);
const engine = injector.get(Engine);
expect(engine).toBeNull();
});
it('should provide to an alias', () => {
const injector = createInjector([
Engine, {provide: SportsCar, useClass: SportsCar}, {provide: Car, useExisting: SportsCar}
]);
const car = injector.get(Car);
const sportsCar = injector.get(SportsCar);
expect(car).toBeAnInstanceOf(SportsCar);
expect(car).toBe(sportsCar);
});
it('should support multiProviders', () => {
const injector = createInjector([
Engine, {provide: Car, useClass: SportsCar, multi: true},
{provide: Car, useClass: CarWithOptionalEngine, multi: true}
]);
const cars = injector.get(Car);
expect(cars.length).toEqual(2);
expect(cars[0]).toBeAnInstanceOf(SportsCar);
expect(cars[1]).toBeAnInstanceOf(CarWithOptionalEngine);
});
it('should support multiProviders that are created using useExisting', () => {
const injector =
createInjector([Engine, SportsCar, {provide: Car, useExisting: SportsCar, multi: true}]);
const cars = injector.get(Car);
expect(cars.length).toEqual(1);
expect(cars[0]).toBe(injector.get(SportsCar));
});
it('should throw when the aliased provider does not exist', () => {
const injector = createInjector([{provide: 'car', useExisting: SportsCar}]);
const e = `No provider for ${stringify(SportsCar)}! (car -> ${stringify(SportsCar)})`;
expect(() => injector.get('car')).toThrowError(e);
});
it('should handle forwardRef in useExisting', () => {
const injector = createInjector([
{provide: 'originalEngine', useClass: forwardRef(() => Engine)},
{provide: 'aliasedEngine', useExisting: <any>forwardRef(() => 'originalEngine')}
]);
expect(injector.get('aliasedEngine')).toBeAnInstanceOf(Engine);
});
it('should support overriding factory dependencies', () => {
const injector = createInjector(
[Engine, {provide: Car, useFactory: (e: Engine) => new SportsCar(e), deps: [Engine]}]);
const car = injector.get(Car);
expect(car).toBeAnInstanceOf(SportsCar);
expect(car.engine).toBeAnInstanceOf(Engine);
});
it('should support optional dependencies', () => {
const injector = createInjector([CarWithOptionalEngine]);
const car = injector.get(CarWithOptionalEngine);
expect(car.engine).toEqual(null);
});
it('should flatten passed-in providers', () => {
const injector = createInjector([[[Engine, Car]]]);
const car = injector.get(Car);
expect(car).toBeAnInstanceOf(Car);
});
it('should use the last provider when there are multiple providers for same token', () => {
const injector = createInjector(
[{provide: Engine, useClass: Engine}, {provide: Engine, useClass: TurboEngine}]);
expect(injector.get(Engine)).toBeAnInstanceOf(TurboEngine);
});
it('should use non-type tokens', () => {
const injector = createInjector([{provide: 'token', useValue: 'value'}]);
expect(injector.get('token')).toEqual('value');
});
it('should throw when given invalid providers', () => {
expect(() => createInjector(<any>['blah']))
.toThrowError(
'Invalid provider - only instances of Provider and Type are allowed, got: blah');
});
it('should provide itself', () => {
const parent = createInjector([]);
const child = parent.resolveAndCreateChild([]);
expect(child.get(Injector)).toBe(child);
});
it('should throw when no provider defined', () => {
const injector = createInjector([]);
expect(() => injector.get('NonExisting')).toThrowError('No provider for NonExisting!');
});
it('should show the full path when no provider', () => {
const injector = createInjector([CarWithDashboard, Engine, Dashboard]);
expect(() => injector.get(CarWithDashboard))
.toThrowError(
`No provider for DashboardSoftware! (${stringify(CarWithDashboard)} -> ${stringify(Dashboard)} -> DashboardSoftware)`);
});
it('should throw when trying to instantiate a cyclic dependency', () => {
const injector = createInjector([Car, {provide: Engine, useClass: CyclicEngine}]);
expect(() => injector.get(Car))
.toThrowError(
`Cannot instantiate cyclic dependency! (${stringify(Car)} -> ${stringify(Engine)} -> ${stringify(Car)})`);
});
it('should show the full path when error happens in a constructor', () => {
const providers =
ReflectiveInjector.resolve([Car, {provide: Engine, useClass: BrokenEngine}]);
const injector = new ReflectiveInjector_(providers);
try {
injector.get(Car);
throw 'Must throw';
} catch (e) {
expect(e.message).toContain(
`Error during instantiation of Engine! (${stringify(Car)} -> Engine)`);
expect(getOriginalError(e) instanceof Error).toBeTruthy();
expect(e.keys[0].token).toEqual(Engine);
}
});
it('should instantiate an object after a failed attempt', () => {
let isBroken = true;
const injector = createInjector([
Car, {provide: Engine, useFactory: (() => isBroken ? new BrokenEngine() : new Engine())}
]);
expect(() => injector.get(Car))
.toThrowError('Broken Engine: Error during instantiation of Engine! (Car -> Engine).');
isBroken = false;
expect(injector.get(Car)).toBeAnInstanceOf(Car);
});
it('should support null values', () => {
const injector = createInjector([{provide: 'null', useValue: null}]);
expect(injector.get('null')).toBe(null);
});
describe(`injector`, () => {
it('should instantiate a class without dependencies', () => {
const injector = createInjector([Engine]);
const engine = injector.get(Engine);
expect(engine).toBeAnInstanceOf(Engine);
});
it('should resolve dependencies based on type information', () => {
const injector = createInjector([Engine, Car]);
const car = injector.get(Car);
describe('child', () => {
it('should load instances from parent injector', () => {
expect(car).toBeAnInstanceOf(Car);
expect(car.engine).toBeAnInstanceOf(Engine);
});
it('should resolve dependencies based on @Inject annotation', () => {
const injector = createInjector([TurboEngine, Engine, CarWithInject]);
const car = injector.get(CarWithInject);
expect(car).toBeAnInstanceOf(CarWithInject);
expect(car.engine).toBeAnInstanceOf(TurboEngine);
});
it('should throw when no type and not @Inject (class case)', () => {
expect(() => createInjector([NoAnnotations]))
.toThrowError(
'Cannot resolve all parameters for \'NoAnnotations\'(?). ' +
'Make sure that all the parameters are decorated with Inject or have valid type annotations ' +
'and that \'NoAnnotations\' is decorated with Injectable.');
});
it('should throw when no type and not @Inject (factory case)', () => {
expect(() => createInjector([{provide: 'someToken', useFactory: factoryFn}]))
.toThrowError(
'Cannot resolve all parameters for \'factoryFn\'(?). ' +
'Make sure that all the parameters are decorated with Inject or have valid type annotations ' +
'and that \'factoryFn\' is decorated with Injectable.');
});
it('should cache instances', () => {
const injector = createInjector([Engine]);
const e1 = injector.get(Engine);
const e2 = injector.get(Engine);
expect(e1).toBe(e2);
});
it('should provide to a value', () => {
const injector = createInjector([{provide: Engine, useValue: 'fake engine'}]);
const engine = injector.get(Engine);
expect(engine).toEqual('fake engine');
});
it('should inject dependencies instance of InjectionToken', () => {
const TOKEN = new InjectionToken<string>('token');
const injector = createInjector([
{provide: TOKEN, useValue: 'by token'},
{provide: Engine, useFactory: (v: string) => v, deps: [[TOKEN]]},
]);
const engine = injector.get(Engine);
expect(engine).toEqual('by token');
});
it('should provide to a factory', () => {
function sportsCarFactory(e: any) {
return new SportsCar(e);
}
const injector =
createInjector([Engine, {provide: Car, useFactory: sportsCarFactory, deps: [Engine]}]);
const car = injector.get(Car);
expect(car).toBeAnInstanceOf(SportsCar);
expect(car.engine).toBeAnInstanceOf(Engine);
});
it('should supporting provider to null', () => {
const injector = createInjector([{provide: Engine, useValue: null}]);
const engine = injector.get(Engine);
expect(engine).toBeNull();
});
it('should provide to an alias', () => {
const injector = createInjector([
Engine, {provide: SportsCar, useClass: SportsCar}, {provide: Car, useExisting: SportsCar}
]);
const car = injector.get(Car);
const sportsCar = injector.get(SportsCar);
expect(car).toBeAnInstanceOf(SportsCar);
expect(car).toBe(sportsCar);
});
it('should support multiProviders', () => {
const injector = createInjector([
Engine, {provide: Car, useClass: SportsCar, multi: true},
{provide: Car, useClass: CarWithOptionalEngine, multi: true}
]);
const cars = injector.get(Car);
expect(cars.length).toEqual(2);
expect(cars[0]).toBeAnInstanceOf(SportsCar);
expect(cars[1]).toBeAnInstanceOf(CarWithOptionalEngine);
});
it('should support multiProviders that are created using useExisting', () => {
const injector =
createInjector([Engine, SportsCar, {provide: Car, useExisting: SportsCar, multi: true}]);
const cars = injector.get(Car);
expect(cars.length).toEqual(1);
expect(cars[0]).toBe(injector.get(SportsCar));
});
it('should throw when the aliased provider does not exist', () => {
const injector = createInjector([{provide: 'car', useExisting: SportsCar}]);
const e = `No provider for ${stringify(SportsCar)}! (car -> ${stringify(SportsCar)})`;
expect(() => injector.get('car')).toThrowError(e);
});
it('should handle forwardRef in useExisting', () => {
const injector = createInjector([
{provide: 'originalEngine', useClass: forwardRef(() => Engine)},
{provide: 'aliasedEngine', useExisting: <any>forwardRef(() => 'originalEngine')}
]);
expect(injector.get('aliasedEngine')).toBeAnInstanceOf(Engine);
});
it('should support overriding factory dependencies', () => {
const injector = createInjector(
[Engine, {provide: Car, useFactory: (e: Engine) => new SportsCar(e), deps: [Engine]}]);
const car = injector.get(Car);
expect(car).toBeAnInstanceOf(SportsCar);
expect(car.engine).toBeAnInstanceOf(Engine);
});
it('should support optional dependencies', () => {
const injector = createInjector([CarWithOptionalEngine]);
const car = injector.get(CarWithOptionalEngine);
expect(car.engine).toEqual(null);
});
it('should flatten passed-in providers', () => {
const injector = createInjector([[[Engine, Car]]]);
const car = injector.get(Car);
expect(car).toBeAnInstanceOf(Car);
});
it('should use the last provider when there are multiple providers for same token', () => {
const injector = createInjector(
[{provide: Engine, useClass: Engine}, {provide: Engine, useClass: TurboEngine}]);
expect(injector.get(Engine)).toBeAnInstanceOf(TurboEngine);
});
it('should use non-type tokens', () => {
const injector = createInjector([{provide: 'token', useValue: 'value'}]);
expect(injector.get('token')).toEqual('value');
});
it('should throw when given invalid providers', () => {
expect(() => createInjector(<any>['blah']))
.toThrowError(
'Invalid provider - only instances of Provider and Type are allowed, got: blah');
});
it('should provide itself', () => {
const parent = createInjector([]);
const child = parent.resolveAndCreateChild([]);
expect(child.get(Injector)).toBe(child);
});
it('should throw when no provider defined', () => {
const injector = createInjector([]);
expect(() => injector.get('NonExisting')).toThrowError('No provider for NonExisting!');
});
it('should show the full path when no provider', () => {
const injector = createInjector([CarWithDashboard, Engine, Dashboard]);
expect(() => injector.get(CarWithDashboard))
.toThrowError(`No provider for DashboardSoftware! (${stringify(CarWithDashboard)} -> ${
stringify(Dashboard)} -> DashboardSoftware)`);
});
it('should throw when trying to instantiate a cyclic dependency', () => {
const injector = createInjector([Car, {provide: Engine, useClass: CyclicEngine}]);
expect(() => injector.get(Car))
.toThrowError(`Cannot instantiate cyclic dependency! (${stringify(Car)} -> ${
stringify(Engine)} -> ${stringify(Car)})`);
});
it('should show the full path when error happens in a constructor', () => {
const providers = ReflectiveInjector.resolve([Car, {provide: Engine, useClass: BrokenEngine}]);
const injector = new ReflectiveInjector_(providers);
try {
injector.get(Car);
throw 'Must throw';
} catch (e) {
expect(e.message).toContain(
`Error during instantiation of Engine! (${stringify(Car)} -> Engine)`);
expect(getOriginalError(e) instanceof Error).toBeTruthy();
expect(e.keys[0].token).toEqual(Engine);
}
});
it('should instantiate an object after a failed attempt', () => {
let isBroken = true;
const injector = createInjector(
[Car, {provide: Engine, useFactory: (() => isBroken ? new BrokenEngine() : new Engine())}]);
expect(() => injector.get(Car))
.toThrowError('Broken Engine: Error during instantiation of Engine! (Car -> Engine).');
isBroken = false;
expect(injector.get(Car)).toBeAnInstanceOf(Car);
});
it('should support null values', () => {
const injector = createInjector([{provide: 'null', useValue: null}]);
expect(injector.get('null')).toBe(null);
});
});
describe('child', () => {
it('should load instances from parent injector', () => {
const parent = ReflectiveInjector.resolveAndCreate([Engine]);
const child = parent.resolveAndCreateChild([]);
const engineFromParent = parent.get(Engine);
const engineFromChild = child.get(Engine);
expect(engineFromChild).toBe(engineFromParent);
});
it('should not use the child providers when resolving the dependencies of a parent provider',
() => {
const parent = ReflectiveInjector.resolveAndCreate([Car, Engine]);
const child = parent.resolveAndCreateChild([{provide: Engine, useClass: TurboEngine}]);
const carFromChild = child.get(Car);
expect(carFromChild.engine).toBeAnInstanceOf(Engine);
});
it('should create new instance in a child injector', () => {
const parent = ReflectiveInjector.resolveAndCreate([Engine]);
const child = parent.resolveAndCreateChild([{provide: Engine, useClass: TurboEngine}]);
const engineFromParent = parent.get(Engine);
const engineFromChild = child.get(Engine);
expect(engineFromParent).not.toBe(engineFromChild);
expect(engineFromChild).toBeAnInstanceOf(TurboEngine);
});
it('should give access to parent', () => {
const parent = ReflectiveInjector.resolveAndCreate([]);
const child = parent.resolveAndCreateChild([]);
expect(child.parent).toBe(parent);
});
});
describe('resolveAndInstantiate', () => {
it('should instantiate an object in the context of the injector', () => {
const inj = ReflectiveInjector.resolveAndCreate([Engine]);
const car = inj.resolveAndInstantiate(Car);
expect(car).toBeAnInstanceOf(Car);
expect(car.engine).toBe(inj.get(Engine));
});
it('should not store the instantiated object in the injector', () => {
const inj = ReflectiveInjector.resolveAndCreate([Engine]);
inj.resolveAndInstantiate(Car);
expect(() => inj.get(Car)).toThrowError();
});
});
describe('instantiate', () => {
it('should instantiate an object in the context of the injector', () => {
const inj = ReflectiveInjector.resolveAndCreate([Engine]);
const car = inj.instantiateResolved(ReflectiveInjector.resolve([Car])[0]);
expect(car).toBeAnInstanceOf(Car);
expect(car.engine).toBe(inj.get(Engine));
});
});
describe('depedency resolution', () => {
describe('@Self()', () => {
it('should return a dependency from self', () => {
const inj = ReflectiveInjector.resolveAndCreate([
Engine, {provide: Car, useFactory: (e: Engine) => new Car(e), deps: [[Engine, new Self()]]}
]);
expect(inj.get(Car)).toBeAnInstanceOf(Car);
});
it('should throw when not requested provider on self', () => {
const parent = ReflectiveInjector.resolveAndCreate([Engine]);
const child = parent.resolveAndCreateChild([]);
const child = parent.resolveAndCreateChild(
[{provide: Car, useFactory: (e: Engine) => new Car(e), deps: [[Engine, new Self()]]}]);
const engineFromParent = parent.get(Engine);
const engineFromChild = child.get(Engine);
expect(engineFromChild).toBe(engineFromParent);
expect(() => child.get(Car))
.toThrowError(`No provider for Engine! (${stringify(Car)} -> ${stringify(Engine)})`);
});
});
it('should not use the child providers when resolving the dependencies of a parent provider',
() => {
const parent = ReflectiveInjector.resolveAndCreate([Car, Engine]);
const child = parent.resolveAndCreateChild([{provide: Engine, useClass: TurboEngine}]);
const carFromChild = child.get(Car);
expect(carFromChild.engine).toBeAnInstanceOf(Engine);
});
it('should create new instance in a child injector', () => {
describe('default', () => {
it('should not skip self', () => {
const parent = ReflectiveInjector.resolveAndCreate([Engine]);
const child = parent.resolveAndCreateChild([{provide: Engine, useClass: TurboEngine}]);
const engineFromParent = parent.get(Engine);
const engineFromChild = child.get(Engine);
expect(engineFromParent).not.toBe(engineFromChild);
expect(engineFromChild).toBeAnInstanceOf(TurboEngine);
});
it('should give access to parent', () => {
const parent = ReflectiveInjector.resolveAndCreate([]);
const child = parent.resolveAndCreateChild([]);
expect(child.parent).toBe(parent);
});
});
describe('resolveAndInstantiate', () => {
it('should instantiate an object in the context of the injector', () => {
const inj = ReflectiveInjector.resolveAndCreate([Engine]);
const car = inj.resolveAndInstantiate(Car);
expect(car).toBeAnInstanceOf(Car);
expect(car.engine).toBe(inj.get(Engine));
});
it('should not store the instantiated object in the injector', () => {
const inj = ReflectiveInjector.resolveAndCreate([Engine]);
inj.resolveAndInstantiate(Car);
expect(() => inj.get(Car)).toThrowError();
});
});
describe('instantiate', () => {
it('should instantiate an object in the context of the injector', () => {
const inj = ReflectiveInjector.resolveAndCreate([Engine]);
const car = inj.instantiateResolved(ReflectiveInjector.resolve([Car])[0]);
expect(car).toBeAnInstanceOf(Car);
expect(car.engine).toBe(inj.get(Engine));
});
});
describe('depedency resolution', () => {
describe('@Self()', () => {
it('should return a dependency from self', () => {
const inj = ReflectiveInjector.resolveAndCreate([
Engine,
{provide: Car, useFactory: (e: Engine) => new Car(e), deps: [[Engine, new Self()]]}
]);
expect(inj.get(Car)).toBeAnInstanceOf(Car);
});
it('should throw when not requested provider on self', () => {
const parent = ReflectiveInjector.resolveAndCreate([Engine]);
const child = parent.resolveAndCreateChild(
[{provide: Car, useFactory: (e: Engine) => new Car(e), deps: [[Engine, new Self()]]}]);
expect(() => child.get(Car))
.toThrowError(`No provider for Engine! (${stringify(Car)} -> ${stringify(Engine)})`);
});
});
describe('default', () => {
it('should not skip self', () => {
const parent = ReflectiveInjector.resolveAndCreate([Engine]);
const child = parent.resolveAndCreateChild([
{provide: Engine, useClass: TurboEngine},
{provide: Car, useFactory: (e: Engine) => new Car(e), deps: [Engine]}
]);
expect(child.get(Car).engine).toBeAnInstanceOf(TurboEngine);
});
});
});
describe('resolve', () => {
it('should resolve and flatten', () => {
const providers = ReflectiveInjector.resolve([Engine, [BrokenEngine]]);
providers.forEach(function(b) {
if (!b) return; // the result is a sparse array
expect(b instanceof ResolvedReflectiveProvider_).toBe(true);
});
});
it('should support multi providers', () => {
const provider = ReflectiveInjector.resolve([
{provide: Engine, useClass: BrokenEngine, multi: true},
{provide: Engine, useClass: TurboEngine, multi: true}
])[0];
expect(provider.key.token).toBe(Engine);
expect(provider.multiProvider).toEqual(true);
expect(provider.resolvedFactories.length).toEqual(2);
});
it('should support providers as hash', () => {
const provider = ReflectiveInjector.resolve([
{provide: Engine, useClass: BrokenEngine, multi: true},
{provide: Engine, useClass: TurboEngine, multi: true}
])[0];
expect(provider.key.token).toBe(Engine);
expect(provider.multiProvider).toEqual(true);
expect(provider.resolvedFactories.length).toEqual(2);
});
it('should support multi providers with only one provider', () => {
const provider =
ReflectiveInjector.resolve([{provide: Engine, useClass: BrokenEngine, multi: true}])[0];
expect(provider.key.token).toBe(Engine);
expect(provider.multiProvider).toEqual(true);
expect(provider.resolvedFactories.length).toEqual(1);
});
it('should throw when mixing multi providers with regular providers', () => {
expect(() => {
ReflectiveInjector.resolve(
[{provide: Engine, useClass: BrokenEngine, multi: true}, Engine]);
}).toThrowError(/Cannot mix multi providers and regular providers/);
expect(() => {
ReflectiveInjector.resolve(
[Engine, {provide: Engine, useClass: BrokenEngine, multi: true}]);
}).toThrowError(/Cannot mix multi providers and regular providers/);
});
it('should resolve forward references', () => {
const providers = ReflectiveInjector.resolve([
forwardRef(() => Engine),
[{provide: forwardRef(() => BrokenEngine), useClass: forwardRef(() => Engine)}], {
provide: forwardRef(() => String),
useFactory: () => 'OK',
deps: [forwardRef(() => Engine)]
}
const child = parent.resolveAndCreateChild([
{provide: Engine, useClass: TurboEngine},
{provide: Car, useFactory: (e: Engine) => new Car(e), deps: [Engine]}
]);
const engineProvider = providers[0];
const brokenEngineProvider = providers[1];
const stringProvider = providers[2];
expect(engineProvider.resolvedFactories[0].factory() instanceof Engine).toBe(true);
expect(brokenEngineProvider.resolvedFactories[0].factory() instanceof Engine).toBe(true);
expect(stringProvider.resolvedFactories[0].dependencies[0].key)
.toEqual(ReflectiveKey.get(Engine));
expect(child.get(Car).engine).toBeAnInstanceOf(TurboEngine);
});
});
});
it('should support overriding factory dependencies with dependency annotations', () => {
const providers = ReflectiveInjector.resolve([{
provide: 'token',
useFactory: (e: any /** TODO #9100 */) => 'result',
deps: [[new Inject('dep')]]
}]);
const provider = providers[0];
expect(provider.resolvedFactories[0].dependencies[0].key.token).toEqual('dep');
});
it('should allow declaring dependencies with flat arrays', () => {
const resolved = ReflectiveInjector.resolve(
[{provide: 'token', useFactory: (e: any) => e, deps: [new Inject('dep')]}]);
const nestedResolved = ReflectiveInjector.resolve(
[{provide: 'token', useFactory: (e: any) => e, deps: [[new Inject('dep')]]}]);
expect(resolved[0].resolvedFactories[0].dependencies[0].key.token)
.toEqual(nestedResolved[0].resolvedFactories[0].dependencies[0].key.token);
describe('resolve', () => {
it('should resolve and flatten', () => {
const providers = ReflectiveInjector.resolve([Engine, [BrokenEngine]]);
providers.forEach(function(b) {
if (!b) return; // the result is a sparse array
expect(b instanceof ResolvedReflectiveProvider_).toBe(true);
});
});
describe('displayName', () => {
it('should work', () => {
expect((<ReflectiveInjector_>ReflectiveInjector.resolveAndCreate([Engine, BrokenEngine]))
.displayName)
.toEqual('ReflectiveInjector(providers: [ "Engine" , "BrokenEngine" ])');
});
it('should support multi providers', () => {
const provider = ReflectiveInjector.resolve([
{provide: Engine, useClass: BrokenEngine, multi: true},
{provide: Engine, useClass: TurboEngine, multi: true}
])[0];
expect(provider.key.token).toBe(Engine);
expect(provider.multiProvider).toEqual(true);
expect(provider.resolvedFactories.length).toEqual(2);
});
it('should support providers as hash', () => {
const provider = ReflectiveInjector.resolve([
{provide: Engine, useClass: BrokenEngine, multi: true},
{provide: Engine, useClass: TurboEngine, multi: true}
])[0];
expect(provider.key.token).toBe(Engine);
expect(provider.multiProvider).toEqual(true);
expect(provider.resolvedFactories.length).toEqual(2);
});
it('should support multi providers with only one provider', () => {
const provider =
ReflectiveInjector.resolve([{provide: Engine, useClass: BrokenEngine, multi: true}])[0];
expect(provider.key.token).toBe(Engine);
expect(provider.multiProvider).toEqual(true);
expect(provider.resolvedFactories.length).toEqual(1);
});
it('should throw when mixing multi providers with regular providers', () => {
expect(() => {
ReflectiveInjector.resolve([{provide: Engine, useClass: BrokenEngine, multi: true}, Engine]);
}).toThrowError(/Cannot mix multi providers and regular providers/);
expect(() => {
ReflectiveInjector.resolve([Engine, {provide: Engine, useClass: BrokenEngine, multi: true}]);
}).toThrowError(/Cannot mix multi providers and regular providers/);
});
it('should resolve forward references', () => {
const providers = ReflectiveInjector.resolve([
forwardRef(() => Engine),
[{provide: forwardRef(() => BrokenEngine), useClass: forwardRef(() => Engine)}],
{provide: forwardRef(() => String), useFactory: () => 'OK', deps: [forwardRef(() => Engine)]}
]);
const engineProvider = providers[0];
const brokenEngineProvider = providers[1];
const stringProvider = providers[2];
expect(engineProvider.resolvedFactories[0].factory() instanceof Engine).toBe(true);
expect(brokenEngineProvider.resolvedFactories[0].factory() instanceof Engine).toBe(true);
expect(stringProvider.resolvedFactories[0].dependencies[0].key)
.toEqual(ReflectiveKey.get(Engine));
});
it('should support overriding factory dependencies with dependency annotations', () => {
const providers = ReflectiveInjector.resolve([{
provide: 'token',
useFactory: (e: any /** TODO #9100 */) => 'result',
deps: [[new Inject('dep')]]
}]);
const provider = providers[0];
expect(provider.resolvedFactories[0].dependencies[0].key.token).toEqual('dep');
});
it('should allow declaring dependencies with flat arrays', () => {
const resolved = ReflectiveInjector.resolve(
[{provide: 'token', useFactory: (e: any) => e, deps: [new Inject('dep')]}]);
const nestedResolved = ReflectiveInjector.resolve(
[{provide: 'token', useFactory: (e: any) => e, deps: [[new Inject('dep')]]}]);
expect(resolved[0].resolvedFactories[0].dependencies[0].key.token)
.toEqual(nestedResolved[0].resolvedFactories[0].dependencies[0].key.token);
});
});
describe('displayName', () => {
it('should work', () => {
expect((<ReflectiveInjector_>ReflectiveInjector.resolveAndCreate([Engine, BrokenEngine]))
.displayName)
.toEqual('ReflectiveInjector(providers: [ "Engine" , "BrokenEngine" ])');
});
});
})();

View File

@ -12,16 +12,20 @@ import {KeyRegistry} from '@angular/core/src/di/reflective_key';
describe('key', function() {
let registry: KeyRegistry;
beforeEach(function() { registry = new KeyRegistry(); });
beforeEach(function() {
registry = new KeyRegistry();
});
it('should be equal to another key if type is the same',
function() { expect(registry.get('car')).toBe(registry.get('car')); });
it('should be equal to another key if type is the same', function() {
expect(registry.get('car')).toBe(registry.get('car'));
});
it('should not be equal to another key if types are different',
function() { expect(registry.get('car')).not.toBe(registry.get('porsche')); });
it('should return the passed in key',
function() { expect(registry.get(registry.get('car'))).toBe(registry.get('car')); });
it('should not be equal to another key if types are different', function() {
expect(registry.get('car')).not.toBe(registry.get('porsche'));
});
it('should return the passed in key', function() {
expect(registry.get(registry.get('car'))).toBe(registry.get('car'));
});
});
}

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Inject, InjectFlags, InjectionToken, Injector, Optional, Self, SkipSelf, forwardRef} from '@angular/core';
import {forwardRef, Inject, InjectFlags, InjectionToken, Injector, Optional, Self, SkipSelf} from '@angular/core';
import {expect} from '@angular/platform-browser/testing/src/matchers';
import {ivyEnabled, modifiedInIvy} from '@angular/private/testing';
@ -18,7 +18,9 @@ class Engine {
class BrokenEngine {
static PROVIDER = {provide: Engine, useClass: BrokenEngine, deps: []};
constructor() { throw new Error('Broken Engine'); }
constructor() {
throw new Error('Broken Engine');
}
}
class DashboardSoftware {
@ -75,7 +77,7 @@ class NoAnnotations {
constructor(secretDependency: any) {}
}
function factoryFn(a: any){}
function factoryFn(a: any) {}
{
const dynamicProviders = [
@ -88,7 +90,6 @@ function factoryFn(a: any){}
];
modifiedInIvy('Ivy uses R3Injector').describe(`StaticInjector`, () => {
it('should instantiate a class without dependencies', () => {
const injector = Injector.create([Engine.PROVIDER]);
const engine = injector.get(Engine);
@ -133,7 +134,9 @@ function factoryFn(a: any){}
});
it('should provide to a factory', () => {
function sportsCarFactory(e: any) { return new SportsCar(e); }
function sportsCarFactory(e: any) {
return new SportsCar(e);
}
const injector = Injector.create(
[Engine.PROVIDER, {provide: Car, useFactory: sportsCarFactory, deps: [Engine]}]);
@ -187,26 +190,22 @@ function factoryFn(a: any){}
it('should throw when the aliased provider does not exist', () => {
const injector = Injector.create([{provide: 'car', useExisting: SportsCar}]);
const e =
`StaticInjectorError[car -> ${stringify(SportsCar)}]: \n NullInjectorError: No provider for ${stringify(SportsCar)}!`;
const e = `StaticInjectorError[car -> ${
stringify(SportsCar)}]: \n NullInjectorError: No provider for ${stringify(SportsCar)}!`;
expect(() => injector.get('car')).toThrowError(e);
});
it('should handle forwardRef in useExisting', () => {
const injector = Injector.create([
{provide: 'originalEngine', useClass: forwardRef(() => Engine), deps: []}, {
provide: 'aliasedEngine',
useExisting: <any>forwardRef(() => 'originalEngine'),
deps: []
}
{provide: 'originalEngine', useClass: forwardRef(() => Engine), deps: []},
{provide: 'aliasedEngine', useExisting: <any>forwardRef(() => 'originalEngine'), deps: []}
]);
expect(injector.get('aliasedEngine')).toBeAnInstanceOf(Engine);
});
it('should support overriding factory dependencies', () => {
const injector = Injector.create([
Engine.PROVIDER,
{provide: Car, useFactory: (e: Engine) => new SportsCar(e), deps: [Engine]}
Engine.PROVIDER, {provide: Car, useFactory: (e: Engine) => new SportsCar(e), deps: [Engine]}
]);
const car = injector.get<Car>(Car);
@ -249,9 +248,9 @@ function factoryFn(a: any){}
});
it('should throw when missing deps', () => {
expect(() => Injector.create(<any>[{provide: Engine, useClass: Engine}]))
.toThrowError(
'StaticInjectorError[{provide:Engine, useClass:Engine}]: \'deps\' required');
expect(() => Injector.create(<any>[
{provide: Engine, useClass: Engine}
])).toThrowError('StaticInjectorError[{provide:Engine, useClass:Engine}]: \'deps\' required');
});
it('should throw when using reflective API', () => {
@ -289,7 +288,8 @@ function factoryFn(a: any){}
Injector.create([CarWithDashboard.PROVIDER, Engine.PROVIDER, Dashboard.PROVIDER]);
expect(() => injector.get(CarWithDashboard))
.toThrowError(
`StaticInjectorError[${stringify(CarWithDashboard)} -> ${stringify(Dashboard)} -> DashboardSoftware]: \n` +
`StaticInjectorError[${stringify(CarWithDashboard)} -> ${
stringify(Dashboard)} -> DashboardSoftware]: \n` +
' NullInjectorError: No provider for DashboardSoftware!');
});
@ -297,14 +297,21 @@ function factoryFn(a: any){}
const injector = Injector.create([Car.PROVIDER, CyclicEngine.PROVIDER]);
expect(() => injector.get(Car))
.toThrowError(
`StaticInjectorError[${stringify(Car)} -> ${stringify(Engine)} -> ${stringify(Car)}]: Circular dependency`);
.toThrowError(`StaticInjectorError[${stringify(Car)} -> ${stringify(Engine)} -> ${
stringify(Car)}]: Circular dependency`);
});
it('should show the full path when error happens in a constructor', () => {
const error = new Error('MyError');
const injector = Injector.create(
[Car.PROVIDER, {provide: Engine, useFactory: () => { throw error; }, deps: []}]);
const injector = Injector.create([
Car.PROVIDER, {
provide: Engine,
useFactory: () => {
throw error;
},
deps: []
}
]);
try {
injector.get(Car);
@ -345,7 +352,6 @@ function factoryFn(a: any){}
expect(injector.get('null')).toBe(null);
expect(injector.get('undefined')).toBe(undefined);
});
});
@ -495,8 +501,7 @@ function factoryFn(a: any){}
it('should support overriding factory dependencies with dependency annotations', () => {
const injector = Injector.create([
Engine.PROVIDER,
{provide: 'token', useFactory: (e: any) => e, deps: [[new Inject(Engine)]]}
Engine.PROVIDER, {provide: 'token', useFactory: (e: any) => e, deps: [[new Inject(Engine)]]}
]);
expect(injector.get('token')).toBeAnInstanceOf(Engine);