fix(ivy): resolve forward refs in providers (#26766)

PR Close #26766
This commit is contained in:
Kara Erickson 2018-10-25 13:58:33 -07:00 committed by Matias Niemelä
parent f76ce84ae1
commit 2fd4c372d5
2 changed files with 51 additions and 18 deletions

View File

@ -357,20 +357,19 @@ function providerToRecord(provider: SingleProvider): Record<any> {
* @param provider provider to convert to factory
*/
export function providerToFactory(provider: SingleProvider): () => any {
let token = resolveForwardRef(provider);
let factory: (() => any)|undefined = undefined;
if (isTypeProvider(provider)) {
return injectableDefFactory(provider);
return injectableDefFactory(resolveForwardRef(provider));
} else {
token = resolveForwardRef(provider.provide);
if (isValueProvider(provider)) {
factory = () => provider.useValue;
factory = () => resolveForwardRef(provider.useValue);
} else if (isExistingProvider(provider)) {
factory = () => inject(provider.useExisting);
factory = () => inject(resolveForwardRef(provider.useExisting));
} else if (isFactoryProvider(provider)) {
factory = () => provider.useFactory(...injectArgs(provider.deps || []));
} else {
const classRef = (provider as StaticClassProvider | ClassProvider).useClass || token;
const classRef = resolveForwardRef(
(provider as StaticClassProvider | ClassProvider).useClass || provider.provide);
if (hasDeps(provider)) {
factory = () => new (classRef)(...injectArgs(provider.deps));
} else {

View File

@ -708,20 +708,54 @@ describe('providers', () => {
});
});
it('forwardRef', (done) => {
setTimeout(() => {
expectProvidersScenario({
parent: {
providers: [forwardRef(() => ForLater)],
componentAssertion:
() => { expect(directiveInject(ForLater) instanceof ForLater).toBeTruthy(); }
}
});
done();
}, 0);
describe('forwardRef', () => {
it('forwardRef resolves later', (done) => {
setTimeout(() => {
expectProvidersScenario({
parent: {
providers: [forwardRef(() => ForLater)],
componentAssertion:
() => { expect(directiveInject(ForLater) instanceof ForLater).toBeTruthy(); }
}
});
done();
}, 0);
});
class ForLater {}
// The following test that forwardRefs are called, so we don't search for an anon fn
it('ValueProvider wrapped in forwardRef', () => {
expectProvidersScenario({
parent: {
providers:
[{provide: GREETER, useValue: forwardRef(() => { return {greet: 'Value'}; })}],
componentAssertion: () => { expect(directiveInject(GREETER).greet).toEqual('Value'); }
}
});
});
it('ClassProvider wrapped in forwardRef', () => {
expectProvidersScenario({
parent: {
providers: [{provide: GREETER, useClass: forwardRef(() => GreeterClass)}],
componentAssertion: () => { expect(directiveInject(GREETER).greet).toEqual('Class'); }
}
});
});
it('ExistingProvider wrapped in forwardRef', () => {
expectProvidersScenario({
parent: {
providers:
[GreeterClass, {provide: GREETER, useExisting: forwardRef(() => GreeterClass)}],
componentAssertion: () => { expect(directiveInject(GREETER).greet).toEqual('Class'); }
}
});
});
});
});
/*
@ -1692,4 +1726,4 @@ function expectProvidersScenario(defs: {
const fixture = new ComponentFixture(
App, {injector: defs.ngModule ? createInjector(defs.ngModule) : undefined});
expect(fixture.html).toEqual('<parent><view-child>view-child</view-child></parent>');
}
}