Skip to content

Commit 81f1d42

Browse files
chuckjazmhevery
authored andcommitted
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
1 parent 3df1542 commit 81f1d42

File tree

2 files changed

+35
-1
lines changed

2 files changed

+35
-1
lines changed

packages/compiler-cli/test/diagnostics/check_types_spec.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,23 @@ describe('ng type checker', () => {
8787
addTests({fullTemplateTypeCheck: true});
8888
});
8989

90+
describe('regressions', () => {
91+
// #19485
92+
it('should accept if else (TemplateRef)', () => {
93+
accept(
94+
{
95+
'src/app.component.html': `
96+
<div class="text-center" *ngIf="!person; else e">
97+
No person supplied.
98+
</div>
99+
<ng-template #e>
100+
Welcome {{person.name}}!
101+
<ng-template>`
102+
},
103+
{fullTemplateTypeCheck: true});
104+
});
105+
});
106+
90107
function addTests(config: {fullTemplateTypeCheck: boolean}) {
91108
function a(template: string) { accept({'src/app.component.html': template}, config); }
92109

@@ -234,6 +251,7 @@ const QUICKSTART = {
234251
`,
235252
'src/app.module.ts': `
236253
import { NgModule } from '@angular/core';
254+
import { CommonModule } from '@angular/common';
237255
import { AppComponent, APipe, ADirective } from './app.component';
238256
import { LibDirective, LibPipe } from './lib';
239257
@@ -246,7 +264,7 @@ const QUICKSTART = {
246264
@NgModule({
247265
declarations: [ AppComponent, APipe, ADirective ],
248266
bootstrap: [ AppComponent ],
249-
imports: [ LibModule ]
267+
imports: [ LibModule, CommonModule ]
250268
})
251269
export class AppModule { }
252270
`

packages/compiler/src/aot/compiler.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,11 +206,16 @@ export class AotCompiler {
206206
// and they also cause TypeScript to include these files into the program too,
207207
// which will make them part of the analyzedFiles.
208208
const externalReferences: StaticSymbol[] = [
209+
// Add references that are available from all the modules and imports.
209210
...ngModuleMeta.transitiveModule.directives.map(d => d.reference),
210211
...ngModuleMeta.transitiveModule.pipes.map(d => d.reference),
211212
...ngModuleMeta.importedModules.map(m => m.type.reference),
212213
...ngModuleMeta.exportedModules.map(m => m.type.reference),
214+
215+
// Add references that might be inserted by the template compiler.
216+
...this._externalIdentifierReferences([Identifiers.TemplateRef, Identifiers.ElementRef]),
213217
];
218+
214219
const externalReferenceVars = new Map<any, string>();
215220
externalReferences.forEach((ref, typeIndex) => {
216221
if (this._host.isSourceFile(ref.filePath)) {
@@ -248,6 +253,17 @@ export class AotCompiler {
248253
}
249254
}
250255

256+
private _externalIdentifierReferences(references: o.ExternalReference[]): StaticSymbol[] {
257+
const result: StaticSymbol[] = [];
258+
for (let reference of references) {
259+
const token = createTokenForExternalReference(this._reflector, reference);
260+
if (token.identifier) {
261+
result.push(token.identifier.reference);
262+
}
263+
}
264+
return result;
265+
}
266+
251267
private _createTypeCheckBlock(
252268
ctx: OutputContext, componentId: string, moduleMeta: CompileNgModuleMetadata,
253269
compMeta: CompileDirectiveMetadata, directives: CompileIdentifierMetadata[],

0 commit comments

Comments
 (0)