fix(ivy): verify bootstrapped types are Components (#28386)

Prior to this change we didn't verify types passed to bootstrap as a part of NgModule semantics verification. Now we check whether all types passed to bootstrap are actually Components.

PR Close #28386
This commit is contained in:
Andrew Kushnir 2019-01-25 18:18:19 -08:00 committed by Jason Aden
parent 495a9dd445
commit 7d9aa67d8c
2 changed files with 27 additions and 5 deletions

View File

@ -169,6 +169,7 @@ function verifySemanticsOfNgModuleDef(moduleType: NgModuleType): void {
ngModule.imports &&
flatten(ngModule.imports, unwrapModuleWithProvidersImports)
.forEach(verifySemanticsOfNgModuleDef);
ngModule.bootstrap && ngModule.bootstrap.forEach(verifyCorrectBootstrapType);
ngModule.bootstrap && ngModule.bootstrap.forEach(verifyComponentIsPartOfNgModule);
ngModule.entryComponents && ngModule.entryComponents.forEach(verifyComponentIsPartOfNgModule);
}
@ -226,6 +227,13 @@ function verifySemanticsOfNgModuleDef(moduleType: NgModuleType): void {
}
}
function verifyCorrectBootstrapType(type: Type<any>) {
type = resolveForwardRef(type);
if (!getComponentDef(type)) {
errors.push(`${renderStringify(type)} cannot be used as an entry component.`);
}
}
function verifyComponentEntryComponentsIsPartOfNgModule(type: Type<any>) {
type = resolveForwardRef(type);
if (getComponentDef(type)) {

View File

@ -18,7 +18,7 @@ import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {DOCUMENT} from '@angular/platform-browser/src/dom/dom_tokens';
import {expect} from '@angular/platform-browser/testing/src/matchers';
import {fixmeIvy} from '@angular/private/testing';
import {fixmeIvy, modifiedInIvy, onlyInIvy} from '@angular/private/testing';
@Component({selector: 'non-existent', template: ''})
class NonExistentComp {
@ -160,10 +160,8 @@ function bootstrap(
afterEach(destroyPlatform);
// TODO(misko): can't use `fixmeIvy.it` because the `it` is somehow special here.
fixmeIvy(
'FW-876: Bootstrap factory method should throw if bootstrapped Directive is not a Component')
.isEnabled &&
// TODO(misko): can't use `modifiedInIvy.it` because the `it` is somehow special here.
modifiedInIvy('bootstrapping non-Component throws in View Engine').isEnabled &&
it('should throw if bootstrapped Directive is not a Component',
inject([AsyncTestCompleter], (done: AsyncTestCompleter) => {
const logger = new MockConsole();
@ -176,6 +174,22 @@ function bootstrap(
done.done();
}));
// TODO(misko): can't use `onlyInIvy.it` because the `it` is somehow special here.
onlyInIvy('bootstrapping non-Component rejects Promise in Ivy').isEnabled &&
it('should throw if bootstrapped Directive is not a Component',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
const logger = new MockConsole();
const errorHandler = new ErrorHandler();
(errorHandler as any)._console = logger as any;
bootstrap(HelloRootDirectiveIsNotCmp, [
{provide: ErrorHandler, useValue: errorHandler}
]).catch((error: Error) => {
expect(error).toEqual(
new Error(`HelloRootDirectiveIsNotCmp cannot be used as an entry component.`));
async.done();
});
}));
it('should throw if no element is found',
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
const logger = new MockConsole();