From a95d65241c12b721b377a8b05a0ce66b432b769c Mon Sep 17 00:00:00 2001 From: Chuck Jazdzewski Date: Tue, 20 Sep 2016 14:54:53 -0700 Subject: [PATCH] fix(compiler): Safe property access expressions work in event bindings (#11724) --- .../src/view_compiler/expression_converter.ts | 6 +++--- .../test/linker/regression_integration_spec.ts | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/modules/@angular/compiler/src/view_compiler/expression_converter.ts b/modules/@angular/compiler/src/view_compiler/expression_converter.ts index fd44f95452..5fc635c58c 100644 --- a/modules/@angular/compiler/src/view_compiler/expression_converter.ts +++ b/modules/@angular/compiler/src/view_compiler/expression_converter.ts @@ -340,7 +340,7 @@ class _AstToIrVisitor implements cdAst.AstVisitor { // Notice that the first guard condition is the left hand of the left most safe access node // which comes in as leftMostSafe to this routine. - let guardedExpression = this.visit(leftMostSafe.receiver, mode); + let guardedExpression = this.visit(leftMostSafe.receiver, _Mode.Expression); let temporary: o.ReadVarExpr; if (this.needsTemporary(leftMostSafe.receiver)) { // If the expression has method calls or pipes then we need to save the result into a @@ -369,7 +369,7 @@ class _AstToIrVisitor implements cdAst.AstVisitor { } // Recursively convert the node now without the guarded member access. - const access = this.visit(ast, mode); + const access = this.visit(ast, _Mode.Expression); // Remove the mapping. This is not strictly required as the converter only traverses each node // once but is safer if the conversion is changed to traverse the nodes more than once. @@ -381,7 +381,7 @@ class _AstToIrVisitor implements cdAst.AstVisitor { } // Produce the conditional - return condition.conditional(o.literal(null), access); + return convertToStatementIfNeeded(mode, condition.conditional(o.literal(null), access)); } // Given a expression of the form a?.b.c?.d.e the the left most safe node is diff --git a/modules/@angular/core/test/linker/regression_integration_spec.ts b/modules/@angular/core/test/linker/regression_integration_spec.ts index cf4575058f..838e0bfc98 100644 --- a/modules/@angular/core/test/linker/regression_integration_spec.ts +++ b/modules/@angular/core/test/linker/regression_integration_spec.ts @@ -79,6 +79,24 @@ function declareTests({useJit}: {useJit: boolean}) { expect(fixture.nativeElement).toHaveText('counting method value'); expect(MyCountingComp.calls).toBe(1); }); + + it('should evalute a conditional in a statement binding', () => { + @Component({selector: 'some-comp', template: '

'}) + class SomeComponent { + nullValue: SomeReferencedClass; + } + + class SomeReferencedClass { + click() {} + } + + expect(() => { + const fixture = TestBed.configureTestingModule({declarations: [SomeComponent]}) + .createComponent(SomeComponent); + + fixture.detectChanges(/* checkNoChanges */ false); + }).not.toThrow(); + }); }); describe('providers', () => {