From b51d8dd43876d0bdbcb309015ff876b293027022 Mon Sep 17 00:00:00 2001 From: crisbeto Date: Tue, 4 Jun 2019 22:03:32 +0200 Subject: [PATCH] fix(ivy): error for empty bindings on ng-template (#30829) Fixes Ivy throwing an error if it runs into an empty property binding on an `ng-template` (e.g. ``) by not generating an update instruction for it. Fixes #30801. This PR resoves FW-1356. PR Close #30829 --- .../directives/ng_template_outlet_spec.ts | 14 ++++++++++++ .../compliance/r3_compiler_compliance_spec.ts | 22 +++++++++++++++++++ .../compiler/src/render3/view/template.ts | 11 ++++++---- 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/packages/common/test/directives/ng_template_outlet_spec.ts b/packages/common/test/directives/ng_template_outlet_spec.ts index 9226e5acbe..4f349b1776 100644 --- a/packages/common/test/directives/ng_template_outlet_spec.ts +++ b/packages/common/test/directives/ng_template_outlet_spec.ts @@ -204,6 +204,20 @@ describe('NgTemplateOutlet', () => { fixture.componentInstance.value = 'baz'; detectChangesAndExpectText(''); }); + + // https://github.com/angular/angular/issues/30801 + it('should not throw if the context is left blank', () => { + const template = ` + test + + `; + + expect(() => { + fixture = createTestComponent(template); + detectChangesAndExpectText('test'); + }).not.toThrow(); + }); + }); @Injectable() diff --git a/packages/compiler-cli/test/compliance/r3_compiler_compliance_spec.ts b/packages/compiler-cli/test/compliance/r3_compiler_compliance_spec.ts index 82b4379423..78b52bc5a4 100644 --- a/packages/compiler-cli/test/compliance/r3_compiler_compliance_spec.ts +++ b/packages/compiler-cli/test/compliance/r3_compiler_compliance_spec.ts @@ -2932,6 +2932,28 @@ describe('compiler compliance', () => { expectEmit(source, SomeDirectiveDefinition, 'Incorrect SomeDirective.ngDirectiveDef'); }); + it('should not throw for empty property bindings on ng-template', () => { + const files = { + app: { + 'example.ts': ` + import {Component, NgModule} from '@angular/core'; + + @Component({ + selector: 'my-app', + template: '' + }) + export class MyComponent { + } + + @NgModule({declarations: [MyComponent]}) + export class MyModule {}` + } + }; + + expect(() => compile(files, angularFiles)).not.toThrow(); + }); + + }); describe('inherited base classes', () => { diff --git a/packages/compiler/src/render3/view/template.ts b/packages/compiler/src/render3/view/template.ts index d7316a84af..2a742933b4 100644 --- a/packages/compiler/src/render3/view/template.ts +++ b/packages/compiler/src/render3/view/template.ts @@ -1024,10 +1024,13 @@ export class TemplateDefinitionBuilder implements t.Visitor, LocalResolver attrs.forEach(input => { if (input instanceof t.BoundAttribute) { const value = input.value.visit(this._valueConverter); - this.allocateBindingSlots(value); - this.updateInstruction( - templateIndex, template.sourceSpan, R3.property, - () => [o.literal(input.name), this.convertPropertyBinding(context, value, true)]); + + if (value !== undefined) { + this.allocateBindingSlots(value); + this.updateInstruction( + templateIndex, template.sourceSpan, R3.property, + () => [o.literal(input.name), this.convertPropertyBinding(context, value, true)]); + } } }); }