diff --git a/packages/core/src/linker/compiler.ts b/packages/core/src/linker/compiler.ts index d0bfaad9da..25d572667c 100644 --- a/packages/core/src/linker/compiler.ts +++ b/packages/core/src/linker/compiler.ts @@ -12,6 +12,8 @@ import {StaticProvider} from '../di/interface/provider'; import {MissingTranslationStrategy} from '../i18n/tokens'; import {Type} from '../interface/type'; import {ViewEncapsulation} from '../metadata'; +import {ComponentFactory as ComponentFactoryR3} from '../render3/component_ref'; +import {getComponentDef, getNgModuleDef} from '../render3/definition'; import {NgModuleFactory as NgModuleFactoryR3} from '../render3/ng_module_ref'; import {ComponentFactory} from './component_factory'; @@ -56,7 +58,14 @@ const Compiler_compileModuleAndAllComponentsSync__PRE_R3__: (moduleType: Type export const Compiler_compileModuleAndAllComponentsSync__POST_R3__: (moduleType: Type) => ModuleWithComponentFactories = function(moduleType: Type): ModuleWithComponentFactories { - return new ModuleWithComponentFactories(Compiler_compileModuleSync__POST_R3__(moduleType), []); + const ngModuleFactory = Compiler_compileModuleSync__POST_R3__(moduleType); + const moduleDef = getNgModuleDef(moduleType) !; + const componentFactories = moduleDef.declarations.reduce((factories, declaration) => { + const componentDef = getComponentDef(declaration); + componentDef && factories.push(new ComponentFactoryR3(componentDef)); + return factories; + }, [] as ComponentFactory[]); + return new ModuleWithComponentFactories(ngModuleFactory, componentFactories); }; const Compiler_compileModuleAndAllComponentsSync = Compiler_compileModuleAndAllComponentsSync__PRE_R3__; diff --git a/packages/core/test/linker/integration_spec.ts b/packages/core/test/linker/integration_spec.ts index 067d8a6bfe..ef8343d4db 100644 --- a/packages/core/test/linker/integration_spec.ts +++ b/packages/core/test/linker/integration_spec.ts @@ -1097,45 +1097,44 @@ function declareTests(config?: {useJit: boolean}) { .toHaveText('dynamic greet'); })); - fixmeIvy('FW-929: ModuleWithComponentFactories.componentFactories is never filled in') - .it('should create a component that has been freshly compiled', () => { - @Component({template: ''}) - class RootComp { - constructor(public vc: ViewContainerRef) {} - } + it('should create a component that has been freshly compiled', () => { + @Component({template: ''}) + class RootComp { + constructor(public vc: ViewContainerRef) {} + } - @NgModule({ - declarations: [RootComp], - providers: [{provide: 'someToken', useValue: 'someRootValue'}], - }) - class RootModule { - } + @NgModule({ + declarations: [RootComp], + providers: [{provide: 'someToken', useValue: 'someRootValue'}], + }) + class RootModule { + } - @Component({template: ''}) - class MyComp { - constructor(@Inject('someToken') public someToken: string) {} - } + @Component({template: ''}) + class MyComp { + constructor(@Inject('someToken') public someToken: string) {} + } - @NgModule({ - declarations: [MyComp], - providers: [{provide: 'someToken', useValue: 'someValue'}], - }) - class MyModule { - } + @NgModule({ + declarations: [MyComp], + providers: [{provide: 'someToken', useValue: 'someValue'}], + }) + class MyModule { + } - const compFixture = TestBed.configureTestingModule({imports: [RootModule]}) - .createComponent(RootComp); - const compiler = TestBed.get(Compiler); - const myCompFactory = - >compiler.compileModuleAndAllComponentsSync(MyModule) - .componentFactories[0]; + const compFixture = + TestBed.configureTestingModule({imports: [RootModule]}).createComponent(RootComp); + const compiler = TestBed.get(Compiler); + const myCompFactory = + >compiler.compileModuleAndAllComponentsSync(MyModule) + .componentFactories[0]; - // Note: the ComponentFactory was created directly via the compiler, i.e. it - // does not have an association to an NgModuleRef. - // -> expect the providers of the module that the view container belongs to. - const compRef = compFixture.componentInstance.vc.createComponent(myCompFactory); - expect(compRef.instance.someToken).toBe('someRootValue'); - }); + // Note: the ComponentFactory was created directly via the compiler, i.e. it + // does not have an association to an NgModuleRef. + // -> expect the providers of the module that the view container belongs to. + const compRef = compFixture.componentInstance.vc.createComponent(myCompFactory); + expect(compRef.instance.someToken).toBe('someRootValue'); + }); it('should create a component with the passed NgModuleRef', () => { @Component({template: ''}) diff --git a/packages/core/testing/src/r3_test_bed.ts b/packages/core/testing/src/r3_test_bed.ts index 7c7e4cdfdf..32080dbff3 100644 --- a/packages/core/testing/src/r3_test_bed.ts +++ b/packages/core/testing/src/r3_test_bed.ts @@ -700,6 +700,17 @@ export class TestBedRender3 implements Injector, TestBed { }); } + /** + * @internal + */ + _getComponentFactories(moduleType: NgModuleType): ComponentFactory[] { + return moduleType.ngModuleDef.declarations.reduce((factories, declaration) => { + const componentDef = (declaration as any).ngComponentDef; + componentDef && factories.push(new ComponentFactory(componentDef, this._moduleRef)); + return factories; + }, [] as ComponentFactory[]); + } + /** * Check whether the module scoping queue should be flushed, and flush it if needed. * @@ -757,7 +768,9 @@ class R3TestCompiler implements Compiler { } compileModuleAndAllComponentsSync(moduleType: Type): ModuleWithComponentFactories { - return new ModuleWithComponentFactories(this.compileModuleSync(moduleType), []); + const ngModuleFactory = this.compileModuleSync(moduleType); + const componentFactories = this.testBed._getComponentFactories(moduleType as NgModuleType); + return new ModuleWithComponentFactories(ngModuleFactory, componentFactories); } compileModuleAndAllComponentsAsync(moduleType: Type):