fix(ivy): support forward refs in provider deps (#30201)

Currently, we are not properly resolving forward refs when they appear
in deps for providers created with the useFactory strategy. This commit
wraps provider deps in the resolveForwardRef call so the tokens are
passed into the inject function as expected.

PR Close #30201
This commit is contained in:
Kara Erickson 2019-04-29 15:21:49 -07:00
parent e53cf81689
commit 00ffc03523
2 changed files with 41 additions and 2 deletions

View File

@ -9,6 +9,7 @@
import {Type} from '../interface/type';
import {stringify} from '../util/stringify';
import {resolveForwardRef} from './forward_ref';
import {InjectionToken} from './injection_token';
import {Injector} from './injector';
import {getInjectableDef, ɵɵInjectableDef} from './interface/defs';
@ -134,7 +135,7 @@ export function injectRootLimpMode<T>(
export function injectArgs(types: (Type<any>| InjectionToken<any>| any[])[]): any[] {
const args: any[] = [];
for (let i = 0; i < types.length; i++) {
const arg = types[i];
const arg = resolveForwardRef(types[i]);
if (Array.isArray(arg)) {
if (arg.length === 0) {
throw new Error('Arguments array must have arguments.');

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {Component, Directive, Inject, Injectable, InjectionToken} from '@angular/core';
import {Component, Directive, Inject, Injectable, InjectionToken, NgModule, forwardRef} from '@angular/core';
import {TestBed, async, inject} from '@angular/core/testing';
import {By} from '@angular/platform-browser';
import {onlyInIvy} from '@angular/private/testing';
@ -283,4 +283,42 @@ describe('providers', () => {
})));
});
});
describe('forward refs', () => {
it('should support forward refs in provider deps', () => {
class MyService {
constructor(public dep: {value: string}) {}
}
class OtherService {
value = 'one';
}
@Component({selector: 'app-comp', template: ``})
class AppComp {
constructor(public myService: MyService) {}
}
@NgModule({
providers: [
OtherService, {
provide: MyService,
useFactory: (dep: {value: string}) => new MyService(dep),
deps: [forwardRef(() => OtherService)]
}
],
declarations: [AppComp]
})
class MyModule {
}
TestBed.configureTestingModule({imports: [MyModule]});
const fixture = TestBed.createComponent(AppComp);
expect(fixture.componentInstance.myService.dep.value).toBe('one');
});
});
});