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:
parent
495a9dd445
commit
7d9aa67d8c
@ -169,6 +169,7 @@ function verifySemanticsOfNgModuleDef(moduleType: NgModuleType): void {
|
|||||||
ngModule.imports &&
|
ngModule.imports &&
|
||||||
flatten(ngModule.imports, unwrapModuleWithProvidersImports)
|
flatten(ngModule.imports, unwrapModuleWithProvidersImports)
|
||||||
.forEach(verifySemanticsOfNgModuleDef);
|
.forEach(verifySemanticsOfNgModuleDef);
|
||||||
|
ngModule.bootstrap && ngModule.bootstrap.forEach(verifyCorrectBootstrapType);
|
||||||
ngModule.bootstrap && ngModule.bootstrap.forEach(verifyComponentIsPartOfNgModule);
|
ngModule.bootstrap && ngModule.bootstrap.forEach(verifyComponentIsPartOfNgModule);
|
||||||
ngModule.entryComponents && ngModule.entryComponents.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>) {
|
function verifyComponentEntryComponentsIsPartOfNgModule(type: Type<any>) {
|
||||||
type = resolveForwardRef(type);
|
type = resolveForwardRef(type);
|
||||||
if (getComponentDef(type)) {
|
if (getComponentDef(type)) {
|
||||||
|
@ -18,7 +18,7 @@ import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
|
|||||||
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
|
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
|
||||||
import {DOCUMENT} from '@angular/platform-browser/src/dom/dom_tokens';
|
import {DOCUMENT} from '@angular/platform-browser/src/dom/dom_tokens';
|
||||||
import {expect} from '@angular/platform-browser/testing/src/matchers';
|
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: ''})
|
@Component({selector: 'non-existent', template: ''})
|
||||||
class NonExistentComp {
|
class NonExistentComp {
|
||||||
@ -160,10 +160,8 @@ function bootstrap(
|
|||||||
|
|
||||||
afterEach(destroyPlatform);
|
afterEach(destroyPlatform);
|
||||||
|
|
||||||
// TODO(misko): can't use `fixmeIvy.it` because the `it` is somehow special here.
|
// TODO(misko): can't use `modifiedInIvy.it` because the `it` is somehow special here.
|
||||||
fixmeIvy(
|
modifiedInIvy('bootstrapping non-Component throws in View Engine').isEnabled &&
|
||||||
'FW-876: Bootstrap factory method should throw if bootstrapped Directive is not a Component')
|
|
||||||
.isEnabled &&
|
|
||||||
it('should throw if bootstrapped Directive is not a Component',
|
it('should throw if bootstrapped Directive is not a Component',
|
||||||
inject([AsyncTestCompleter], (done: AsyncTestCompleter) => {
|
inject([AsyncTestCompleter], (done: AsyncTestCompleter) => {
|
||||||
const logger = new MockConsole();
|
const logger = new MockConsole();
|
||||||
@ -176,6 +174,22 @@ function bootstrap(
|
|||||||
done.done();
|
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',
|
it('should throw if no element is found',
|
||||||
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
|
||||||
const logger = new MockConsole();
|
const logger = new MockConsole();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user