diff --git a/modules/@angular/compiler/src/metadata_resolver.ts b/modules/@angular/compiler/src/metadata_resolver.ts index bde95f4870..8331cea54e 100644 --- a/modules/@angular/compiler/src/metadata_resolver.ts +++ b/modules/@angular/compiler/src/metadata_resolver.ts @@ -351,17 +351,23 @@ export class CompileMetadataResolver { } }); moduleMeta.declaredDirectives.forEach((dirMeta) => { - dirMeta.entryComponents.forEach((entryComponent) => { - if (!moduleMeta.transitiveModule.directivesSet.has(entryComponent.runtime)) { - throw new BaseException( - `Component ${stringify(dirMeta.type.runtime)} in NgModule ${stringify(moduleMeta.type.runtime)} uses ${stringify(entryComponent.runtime)} via "entryComponents" but it was neither declared nor imported into the module!`); + dirMeta.entryComponents.forEach((entryComponentType) => { + if (!moduleMeta.transitiveModule.directivesSet.has(entryComponentType.runtime)) { + this._addDirectiveToModule( + this.getDirectiveMetadata(entryComponentType.runtime), moduleMeta.type.runtime, + moduleMeta.transitiveModule, moduleMeta.declaredDirectives); + this._console.warn( + `Component ${stringify(dirMeta.type.runtime)} in NgModule ${stringify(moduleMeta.type.runtime)} uses ${stringify(entryComponentType.runtime)} via "entryComponents" but it was neither declared nor imported into the module! This warning will become an error after final.`); } }); }); moduleMeta.entryComponents.forEach((entryComponentType) => { if (!moduleMeta.transitiveModule.directivesSet.has(entryComponentType.runtime)) { - throw new BaseException( - `NgModule ${stringify(moduleMeta.type.runtime)} uses ${stringify(entryComponentType.runtime)} via "entryComponents" but it was neither declared nor imported!`); + this._addDirectiveToModule( + this.getDirectiveMetadata(entryComponentType.runtime), moduleMeta.type.runtime, + moduleMeta.transitiveModule, moduleMeta.declaredDirectives); + this._console.warn( + `NgModule ${stringify(moduleMeta.type.runtime)} uses ${stringify(entryComponentType.runtime)} via "entryComponents" but it was neither declared nor imported! This warning will become an error after final.`); } }); } diff --git a/modules/@angular/core/test/linker/entry_components_integration_spec.ts b/modules/@angular/core/test/linker/entry_components_integration_spec.ts index 2b425d288e..2766d25951 100644 --- a/modules/@angular/core/test/linker/entry_components_integration_spec.ts +++ b/modules/@angular/core/test/linker/entry_components_integration_spec.ts @@ -7,20 +7,33 @@ */ import {AsyncTestCompleter, beforeEach, ddescribe, xdescribe, describe, expect, iit, inject, beforeEachProviders, it, xit,} from '@angular/core/testing/testing_internal'; -import {TestComponentBuilder, configureModule} from '@angular/core/testing'; +import {TestComponentBuilder, configureModule, configureCompiler} from '@angular/core/testing'; import {Component, ComponentFactoryResolver, NoComponentFactoryError, forwardRef, ANALYZE_FOR_ENTRY_COMPONENTS, ViewMetadata} from '@angular/core'; import {stringify} from '../../src/facade/lang'; +import {Console} from '../../src/console'; export function main() { describe('jit', () => { declareTests({useJit: true}); }); describe('no jit', () => { declareTests({useJit: false}); }); } +class DummyConsole implements Console { + public warnings: string[] = []; + + log(message: string) {} + warn(message: string) { this.warnings.push(message); } +} + function declareTests({useJit}: {useJit: boolean}) { describe('@Component.entryComponents', function() { - beforeEach(() => { configureModule({declarations: [MainComp, ChildComp, NestedChildComp]}); }); + var console: DummyConsole; + beforeEach(() => { + console = new DummyConsole(); + configureCompiler({useJit: useJit, providers: [{provide: Console, useValue: console}]}); + configureModule({declarations: [MainComp, ChildComp, NestedChildComp]}); + }); - it('should error if the component was not declared nor imported by the module', + it('should warn and auto declare if the component was not declared nor imported by the module', inject([TestComponentBuilder], (tcb: TestComponentBuilder) => { @Component({selector: 'child', template: ''}) @@ -31,9 +44,14 @@ function declareTests({useJit}: {useJit: boolean}) { class SomeComp { } - expect(() => tcb.createSync(SomeComp)) - .toThrowError( - `Component ${stringify(SomeComp)} in NgModule DynamicTestModule uses ${stringify(ChildComp)} via "entryComponents" but it was neither declared nor imported into the module!`); + const compFixture = tcb.createSync(SomeComp); + const cf = compFixture.componentRef.injector.get(ComponentFactoryResolver) + .resolveComponentFactory(ChildComp); + expect(cf.componentType).toBe(ChildComp); + + expect(console.warnings).toEqual([ + `Component ${stringify(SomeComp)} in NgModule DynamicTestModule uses ${stringify(ChildComp)} via "entryComponents" but it was neither declared nor imported into the module! This warning will become an error after final.` + ]); })); diff --git a/modules/@angular/core/test/linker/ng_module_integration_spec.ts b/modules/@angular/core/test/linker/ng_module_integration_spec.ts index 986129fcb7..24740b3d17 100644 --- a/modules/@angular/core/test/linker/ng_module_integration_spec.ts +++ b/modules/@angular/core/test/linker/ng_module_integration_spec.ts @@ -164,16 +164,6 @@ function declareTests({useJit}: {useJit: boolean}) { `Can't export pipe ${stringify(SomePipe)} from ${stringify(SomeModule)} as it was neither declared nor imported!`); }); - it('should error when using an entryComponent that was neither declared nor imported', () => { - @NgModule({entryComponents: [SomeComp]}) - class SomeModule { - } - - expect(() => createModule(SomeModule)) - .toThrowError( - `NgModule ${stringify(SomeModule)} uses ${stringify(SomeComp)} via "entryComponents" but it was neither declared nor imported!`); - }); - it('should error if a directive is declared in more than 1 module', () => { @NgModule({declarations: [SomeDirective]}) class Module1 { @@ -281,6 +271,21 @@ function declareTests({useJit}: {useJit: boolean}) { .toBe(SomeComp); }); + it('should warn and auto declare when using an entryComponent that was neither declared nor imported', + () => { + @NgModule({entryComponents: [SomeComp]}) + class SomeModule { + } + + const ngModule = createModule(SomeModule); + expect(ngModule.componentFactoryResolver.resolveComponentFactory(SomeComp).componentType) + .toBe(SomeComp); + + expect(console.warnings).toEqual([ + `NgModule ${stringify(SomeModule)} uses ${stringify(SomeComp)} via "entryComponents" but it was neither declared nor imported! This warning will become an error after final.` + ]); + }); + it('should entryComponents ComponentFactories via ANALYZE_FOR_ENTRY_COMPONENTS', () => { @NgModule({ declarations: [SomeComp],