From b61784948afb3e5d08c4f55abeb25b146beebda3 Mon Sep 17 00:00:00 2001 From: Alex Rickabaugh Date: Fri, 24 May 2019 14:37:52 -0700 Subject: [PATCH] fix(ivy): template inputs/outputs should not be bound in template scope (#30669) The R3TargetBinder "binds" an Angular template AST, computing semantic information regarding the template and making it accessible. One of the binding passes previously had a bug, where for the following template:
which desugars to:
would have the `[ngIf]` binding processed twice - in both the scope which contains the `` and the scope inside the template. The bug arises because during the latter, `foo` is a variable defined by `let-foo`, and so the R3TargetBinder would incorrectly learn that `foo` inside `[ngIf]` maps to that variable. This commit fixes the bug by only processing inputs, outputs, and templateAttrs from `Template`s in the outer scope. PR Close #30669 --- .../test/ngtsc/template_typecheck_spec.ts | 25 +++++++++++++++++++ .../compiler/src/render3/view/t2_binder.ts | 8 ++---- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/packages/compiler-cli/test/ngtsc/template_typecheck_spec.ts b/packages/compiler-cli/test/ngtsc/template_typecheck_spec.ts index 09116d003a..2ed017e3e9 100644 --- a/packages/compiler-cli/test/ngtsc/template_typecheck_spec.ts +++ b/packages/compiler-cli/test/ngtsc/template_typecheck_spec.ts @@ -270,6 +270,31 @@ describe('ngtsc type checking', () => { expect(diags[0].messageText).toContain('does_not_exist'); }); + it('should property type-check a microsyntax variable with the same name as the expression', + () => { + env.write('test.ts', ` + import {CommonModule} from '@angular/common'; + import {Component, Input, NgModule} from '@angular/core'; + + @Component({ + selector: 'test', + template: '
{{foo}}
', + }) + export class TestCmp { + foo: any; + } + + @NgModule({ + declarations: [TestCmp], + imports: [CommonModule], + }) + export class Module {} + `); + + const diags = env.driveDiagnostics(); + expect(diags.length).toBe(0); + }); + it('should properly type-check inherited directives', () => { env.write('test.ts', ` import {Component, Directive, Input, NgModule} from '@angular/core'; diff --git a/packages/compiler/src/render3/view/t2_binder.ts b/packages/compiler/src/render3/view/t2_binder.ts index d67b353551..a1eb09df4b 100644 --- a/packages/compiler/src/render3/view/t2_binder.ts +++ b/packages/compiler/src/render3/view/t2_binder.ts @@ -372,12 +372,8 @@ class TemplateBinder extends RecursiveAstVisitor implements Visitor { private ingest(template: Template|Node[]): void { if (template instanceof Template) { - // For s, process inputs, outputs, template attributes, - // variables, and child nodes. - // References were processed in the scope of the containing template. - template.inputs.forEach(this.visitNode); - template.outputs.forEach(this.visitNode); - template.templateAttrs.forEach(this.visitNode); + // For s, process only variables and child nodes. Inputs, outputs, templateAttrs, + // and references were all processed in the scope of the containing template. template.variables.forEach(this.visitNode); template.children.forEach(this.visitNode);