fix(compiler): emit correct type-check-blocks with TemplateRef's (#20463)
The type-check block generated with `"fullTemplateTypeCheck"` was invalid if the it contained a template ref as would be generated using the `else` micro-syntax of `NgIf`. Fixes: #19485 PR Close #20463
This commit is contained in:
parent
368cb5ad4e
commit
68b53c07fd
|
@ -87,6 +87,23 @@ describe('ng type checker', () => {
|
||||||
addTests({fullTemplateTypeCheck: true});
|
addTests({fullTemplateTypeCheck: true});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('regressions', () => {
|
||||||
|
// #19485
|
||||||
|
it('should accept if else (TemplateRef)', () => {
|
||||||
|
accept(
|
||||||
|
{
|
||||||
|
'src/app.component.html': `
|
||||||
|
<div class="text-center" *ngIf="!person; else e">
|
||||||
|
No person supplied.
|
||||||
|
</div>
|
||||||
|
<ng-template #e>
|
||||||
|
Welcome {{person.name}}!
|
||||||
|
<ng-template>`
|
||||||
|
},
|
||||||
|
{fullTemplateTypeCheck: true});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
function addTests(config: {fullTemplateTypeCheck: boolean}) {
|
function addTests(config: {fullTemplateTypeCheck: boolean}) {
|
||||||
function a(template: string) { accept({'src/app.component.html': template}, config); }
|
function a(template: string) { accept({'src/app.component.html': template}, config); }
|
||||||
|
|
||||||
|
@ -234,6 +251,7 @@ const QUICKSTART = {
|
||||||
`,
|
`,
|
||||||
'src/app.module.ts': `
|
'src/app.module.ts': `
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
import { AppComponent, APipe, ADirective } from './app.component';
|
import { AppComponent, APipe, ADirective } from './app.component';
|
||||||
import { LibDirective, LibPipe } from './lib';
|
import { LibDirective, LibPipe } from './lib';
|
||||||
|
|
||||||
|
@ -246,7 +264,7 @@ const QUICKSTART = {
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [ AppComponent, APipe, ADirective ],
|
declarations: [ AppComponent, APipe, ADirective ],
|
||||||
bootstrap: [ AppComponent ],
|
bootstrap: [ AppComponent ],
|
||||||
imports: [ LibModule ]
|
imports: [ LibModule, CommonModule ]
|
||||||
})
|
})
|
||||||
export class AppModule { }
|
export class AppModule { }
|
||||||
`
|
`
|
||||||
|
|
|
@ -206,11 +206,16 @@ export class AotCompiler {
|
||||||
// and they also cause TypeScript to include these files into the program too,
|
// and they also cause TypeScript to include these files into the program too,
|
||||||
// which will make them part of the analyzedFiles.
|
// which will make them part of the analyzedFiles.
|
||||||
const externalReferences: StaticSymbol[] = [
|
const externalReferences: StaticSymbol[] = [
|
||||||
|
// Add references that are available from all the modules and imports.
|
||||||
...ngModuleMeta.transitiveModule.directives.map(d => d.reference),
|
...ngModuleMeta.transitiveModule.directives.map(d => d.reference),
|
||||||
...ngModuleMeta.transitiveModule.pipes.map(d => d.reference),
|
...ngModuleMeta.transitiveModule.pipes.map(d => d.reference),
|
||||||
...ngModuleMeta.importedModules.map(m => m.type.reference),
|
...ngModuleMeta.importedModules.map(m => m.type.reference),
|
||||||
...ngModuleMeta.exportedModules.map(m => m.type.reference),
|
...ngModuleMeta.exportedModules.map(m => m.type.reference),
|
||||||
|
|
||||||
|
// Add references that might be inserted by the template compiler.
|
||||||
|
...this._externalIdentifierReferences([Identifiers.TemplateRef, Identifiers.ElementRef]),
|
||||||
];
|
];
|
||||||
|
|
||||||
const externalReferenceVars = new Map<any, string>();
|
const externalReferenceVars = new Map<any, string>();
|
||||||
externalReferences.forEach((ref, typeIndex) => {
|
externalReferences.forEach((ref, typeIndex) => {
|
||||||
if (this._host.isSourceFile(ref.filePath)) {
|
if (this._host.isSourceFile(ref.filePath)) {
|
||||||
|
@ -248,6 +253,17 @@ export class AotCompiler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _externalIdentifierReferences(references: o.ExternalReference[]): StaticSymbol[] {
|
||||||
|
const result: StaticSymbol[] = [];
|
||||||
|
for (let reference of references) {
|
||||||
|
const token = createTokenForExternalReference(this._reflector, reference);
|
||||||
|
if (token.identifier) {
|
||||||
|
result.push(token.identifier.reference);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private _createTypeCheckBlock(
|
private _createTypeCheckBlock(
|
||||||
ctx: OutputContext, componentId: string, moduleMeta: CompileNgModuleMetadata,
|
ctx: OutputContext, componentId: string, moduleMeta: CompileNgModuleMetadata,
|
||||||
compMeta: CompileDirectiveMetadata, directives: CompileIdentifierMetadata[],
|
compMeta: CompileDirectiveMetadata, directives: CompileIdentifierMetadata[],
|
||||||
|
|
Loading…
Reference in New Issue