fix(ivy): resolve `forwardRefs` correctly in TestBed (JIT) (#27737)

Forward refs in some places (like imports/export/providers/viewProviders/queries) were not resolved before passing to compilation phase. Now we resolve missing refs before invoking compile function.

PR Close #27737
This commit is contained in:
Andrew Kushnir 2018-12-18 13:36:19 -08:00 committed by Ben Lesh
parent 1dc95c41eb
commit a9790018df
4 changed files with 21 additions and 20 deletions

View File

@ -7,6 +7,7 @@
*/
import {ComponentType} from '..';
import {resolveForwardRef} from '../../di/forward_ref';
import {Query} from '../../metadata/di';
import {Component, Directive} from '../../metadata/directives';
import {componentNeedsResolution, maybeQueueResolutionOfComponentResources} from '../../metadata/resource_loading';
@ -155,7 +156,7 @@ function directiveMetadata(type: Type<any>, metadata: Directive): R3DirectiveMet
}
function convertToR3QueryPredicate(selector: any): any|string[] {
return typeof selector === 'string' ? splitByComma(selector) : selector;
return typeof selector === 'string' ? splitByComma(selector) : resolveForwardRef(selector);
}
export function convertToR3QueryMetadata(propertyName: string, ann: Query): R3QueryMetadataFacade {

View File

@ -107,10 +107,12 @@ export function compileNgModuleDefs(moduleType: NgModuleType, ngModule: NgModule
ngModuleDef = getCompilerFacade().compileNgModule(
angularCoreEnv, `ng://${moduleType.name}/ngModuleDef.js`, {
type: moduleType,
bootstrap: flatten(ngModule.bootstrap || EMPTY_ARRAY),
declarations: declarations,
imports: flatten(ngModule.imports || EMPTY_ARRAY).map(expandModuleWithProviders),
exports: flatten(ngModule.exports || EMPTY_ARRAY).map(expandModuleWithProviders),
bootstrap: flatten(ngModule.bootstrap || EMPTY_ARRAY, resolveForwardRef),
declarations: declarations.map(resolveForwardRef),
imports: flatten(ngModule.imports || EMPTY_ARRAY, resolveForwardRef)
.map(expandModuleWithProviders),
exports: flatten(ngModule.exports || EMPTY_ARRAY, resolveForwardRef)
.map(expandModuleWithProviders),
emitInline: true,
});
}
@ -132,8 +134,8 @@ export function compileNgModuleDefs(moduleType: NgModuleType, ngModule: NgModule
deps: reflectDependencies(moduleType),
providers: ngModule.providers || EMPTY_ARRAY,
imports: [
ngModule.imports || EMPTY_ARRAY,
ngModule.exports || EMPTY_ARRAY,
(ngModule.imports || EMPTY_ARRAY).map(resolveForwardRef),
(ngModule.exports || EMPTY_ARRAY).map(resolveForwardRef),
],
};
ngInjectorDef = getCompilerFacade().compileInjector(
@ -154,8 +156,8 @@ function verifySemanticsOfNgModuleDef(moduleType: NgModuleType): void {
const errors: string[] = [];
ngModuleDef.declarations.forEach(verifyDeclarationsHaveDefinitions);
const combinedDeclarations: Type<any>[] = [
...ngModuleDef.declarations, //
...flatten(ngModuleDef.imports.map(computeCombinedExports)),
...ngModuleDef.declarations.map(resolveForwardRef), //
...flatten(ngModuleDef.imports.map(computeCombinedExports), resolveForwardRef),
];
ngModuleDef.exports.forEach(verifyExportsAreDeclaredOrReExported);
ngModuleDef.declarations.forEach(verifyDeclarationIsUnique);

View File

@ -10,19 +10,16 @@ import {CommonModule} from '@angular/common';
import {Component, ContentChildren, Directive, Inject, NO_ERRORS_SCHEMA, NgModule, QueryList, asNativeElements, forwardRef} from '@angular/core';
import {TestBed} from '@angular/core/testing';
import {expect} from '@angular/platform-browser/testing/src/matchers';
import {fixmeIvy} from '@angular/private/testing';
describe('forwardRef integration', function() {
beforeEach(() => { TestBed.configureTestingModule({imports: [Module], declarations: [App]}); });
fixmeIvy('FW-756: Pipes and directives from imported modules are not taken into account')
.it('should instantiate components which are declared using forwardRef', () => {
const a =
TestBed.configureTestingModule({schemas: [NO_ERRORS_SCHEMA]}).createComponent(App);
a.detectChanges();
expect(asNativeElements(a.debugElement.children)).toHaveText('frame(lock)');
expect(TestBed.get(ModuleFrame)).toBeDefined();
});
it('should instantiate components which are declared using forwardRef', () => {
const a = TestBed.configureTestingModule({schemas: [NO_ERRORS_SCHEMA]}).createComponent(App);
a.detectChanges();
expect(asNativeElements(a.debugElement.children)).toHaveText('frame(lock)');
expect(TestBed.get(ModuleFrame)).toBeDefined();
});
});
@NgModule({

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import {ApplicationInitStatus, Component, Directive, Injector, NgModule, NgZone, Pipe, PlatformRef, Provider, SchemaMetadata, Type, ɵInjectableDef as InjectableDef, ɵNgModuleDef as NgModuleDef, ɵNgModuleTransitiveScopes as NgModuleTransitiveScopes, ɵNgModuleType as NgModuleType, ɵRender3ComponentFactory as ComponentFactory, ɵRender3NgModuleRef as NgModuleRef, ɵcompileComponent as compileComponent, ɵcompileDirective as compileDirective, ɵcompileNgModuleDefs as compileNgModuleDefs, ɵcompilePipe as compilePipe, ɵgetInjectableDef as getInjectableDef, ɵpatchComponentDefWithScope as patchComponentDefWithScope, ɵresetCompiledComponents as resetCompiledComponents, ɵstringify as stringify} from '@angular/core';
import {ApplicationInitStatus, Component, Directive, Injector, NgModule, NgZone, Pipe, PlatformRef, Provider, SchemaMetadata, Type, resolveForwardRef, ɵInjectableDef as InjectableDef, ɵNgModuleDef as NgModuleDef, ɵNgModuleTransitiveScopes as NgModuleTransitiveScopes, ɵNgModuleType as NgModuleType, ɵRender3ComponentFactory as ComponentFactory, ɵRender3NgModuleRef as NgModuleRef, ɵcompileComponent as compileComponent, ɵcompileDirective as compileDirective, ɵcompileNgModuleDefs as compileNgModuleDefs, ɵcompilePipe as compilePipe, ɵgetInjectableDef as getInjectableDef, ɵpatchComponentDefWithScope as patchComponentDefWithScope, ɵresetCompiledComponents as resetCompiledComponents, ɵstringify as stringify} from '@angular/core';
import {ComponentFixture} from './component_fixture';
import {MetadataOverride} from './metadata_override';
@ -493,7 +493,8 @@ export class TestBedRender3 implements Injector, TestBed {
const metadata = this._getMetaWithOverrides(ngModule);
compileNgModuleDefs(moduleType, metadata);
const declarations: Type<any>[] = flatten(ngModule.declarations || EMPTY_ARRAY);
const declarations: Type<any>[] =
flatten(ngModule.declarations || EMPTY_ARRAY, resolveForwardRef);
const compiledComponents: Type<any>[] = [];
// Compile the components, directives and pipes declared by this module