From 48555f95c67ed20f6bd43da8bc1c64078945decb Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Wed, 19 Dec 2018 22:17:38 +0200 Subject: [PATCH] fix(ivy): ensure unique template and listener function identifiers (#27766) Previously, there could be identical template/listener function names for a component's template, if it had multiple similarly structured nested sub-templates or listeners. This resulted in build errors: `Identifier '' has already been declared` This commit fixes this by ensuring that the template index is included in the `contextName` passed to the `TemplateDefinitionBuilder` responsible for processing nested sub-templates. Similarly, the template or element index is included in the listener names. PR Close #27766 --- .../compliance/r3_compiler_compliance_spec.ts | 84 ++++----- .../r3_view_compiler_directives_spec.ts | 78 ++++---- .../compliance/r3_view_compiler_i18n_spec.ts | 92 ++++----- .../r3_view_compiler_listener_spec.ts | 14 +- .../r3_view_compiler_styling_spec.ts | 4 +- .../r3_view_compiler_template_spec.ts | 174 +++++++++++++++--- .../compiler/src/render3/view/template.ts | 15 +- .../bundling/todo/bundle.golden_symbols.json | 12 +- 8 files changed, 296 insertions(+), 177 deletions(-) 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 6fd84a85de..b30455e41c 100644 --- a/packages/compiler-cli/test/compliance/r3_compiler_compliance_spec.ts +++ b/packages/compiler-cli/test/compliance/r3_compiler_compliance_spec.ts @@ -767,7 +767,7 @@ describe('compiler compliance', () => { const MyComponentDefinition = ` const $c1$ = ["foo", ""]; const $c2$ = ["if", ""]; - function MyComponent_li_Template_2(rf, ctx) { + function MyComponent_li_2_Template(rf, ctx) { if (rf & 1) { $r3$.ɵelementStart(0, "li"); $r3$.ɵtext(1); @@ -789,7 +789,7 @@ describe('compiler compliance', () => { template: function MyComponent_Template(rf, ctx) { if (rf & 1) { $r3$.ɵelementStart(0, "ul", null, $c1$); - $r3$.ɵtemplate(2, MyComponent_li_Template_2, 2, 2, "li", $c2$); + $r3$.ɵtemplate(2, MyComponent_li_2_Template, 2, 2, "li", $c2$); $r3$.ɵelementEnd(); } }, @@ -1093,10 +1093,10 @@ describe('compiler compliance', () => { app: { 'spec.ts': ` import {Component, Directive, NgModule, TemplateRef} from '@angular/core'; - + @Component({selector: 'simple', template: '
'}) export class SimpleComponent {} - + @Component({ selector: 'complex', template: \` @@ -1104,10 +1104,10 @@ describe('compiler compliance', () => {
\` }) export class ComplexComponent { } - + @NgModule({declarations: [SimpleComponent, ComplexComponent]}) export class MyModule {} - + @Component({ selector: 'my-app', template: 'content ' @@ -1176,7 +1176,7 @@ describe('compiler compliance', () => { app: { 'spec.ts': ` import {Component, NgModule} from '@angular/core'; - + @Component({ template: \`
@@ -1191,7 +1191,7 @@ describe('compiler compliance', () => { \`, }) class Cmp {} - + @NgModule({ declarations: [Cmp] }) class Module {} ` @@ -1200,20 +1200,20 @@ describe('compiler compliance', () => { const output = ` const $_c0$ = [${AttributeMarker.SelectOnly}, "ngIf"]; const $_c1$ = ["id", "second"]; - function Cmp_div_Template_0(rf, ctx) { if (rf & 1) { + function Cmp_div_0_Template(rf, ctx) { if (rf & 1) { $r3$.ɵelementStart(0, "div", $_c1$); $r3$.ɵprojection(1, 1); $r3$.ɵelementEnd(); } } const $_c4$ = ["id", "third"]; - function Cmp_div_Template_1(rf, ctx) { + function Cmp_div_1_Template(rf, ctx) { if (rf & 1) { $r3$.ɵelementStart(0, "div", $_c4$); $r3$.ɵtext(1, " No ng-content, no instructions generated. "); $r3$.ɵelementEnd(); } } - function Cmp_ng_template_Template_2(rf, ctx) { + function Cmp_ng_template_2_Template(rf, ctx) { if (rf & 1) { $r3$.ɵtext(0, " '*' selector: "); $r3$.ɵprojection(1); @@ -1225,9 +1225,9 @@ describe('compiler compliance', () => { template: function Cmp_Template(rf, ctx) { if (rf & 1) { $r3$.ɵprojectionDef($_c2$, $_c3$); - $r3$.ɵtemplate(0, Cmp_div_Template_0, 2, 0, "div", $_c0$); - $r3$.ɵtemplate(1, Cmp_div_Template_1, 2, 0, "div", $_c0$); - $r3$.ɵtemplate(2, Cmp_ng_template_Template_2, 2, 0, "ng-template"); + $r3$.ɵtemplate(0, Cmp_div_0_Template, 2, 0, "div", $_c0$); + $r3$.ɵtemplate(1, Cmp_div_1_Template, 2, 0, "div", $_c0$); + $r3$.ɵtemplate(2, Cmp_ng_template_2_Template, 2, 0, "ng-template"); } if (rf & 2) { $r3$.ɵelementProperty(0, "ngIf", $r3$.ɵbind(ctx.visible)); @@ -1245,7 +1245,7 @@ describe('compiler compliance', () => { app: { 'spec.ts': ` import {Component, NgModule} from '@angular/core'; - + @Component({ template: \` @@ -1254,7 +1254,7 @@ describe('compiler compliance', () => { - + '*' selector in a template: @@ -1262,7 +1262,7 @@ describe('compiler compliance', () => { \`, }) class Cmp {} - + @NgModule({ declarations: [Cmp] }) class Module {} ` @@ -1270,18 +1270,18 @@ describe('compiler compliance', () => { }; const output = ` - function Cmp_ng_template_ng_template_Template_1(rf, ctx) { + function Cmp_ng_template_1_ng_template_1_Template(rf, ctx) { if (rf & 1) { $r3$.ɵprojection(0, 4); - } + } } - function Cmp_ng_template_Template_1(rf, ctx) { + function Cmp_ng_template_1_Template(rf, ctx) { if (rf & 1) { $r3$.ɵprojection(0, 3); - $r3$.ɵtemplate(1, Cmp_ng_template_ng_template_Template_1, 1, 0, "ng-template"); - } + $r3$.ɵtemplate(1, Cmp_ng_template_1_ng_template_1_Template, 1, 0, "ng-template"); + } } - function Cmp_ng_template_Template_2(rf, ctx) { + function Cmp_ng_template_2_Template(rf, ctx) { if (rf & 1) { $r3$.ɵtext(0, " '*' selector in a template: "); $r3$.ɵprojection(1); @@ -1294,10 +1294,10 @@ describe('compiler compliance', () => { if (rf & 1) { $r3$.ɵprojectionDef($_c2$, $_c3$); $r3$.ɵprojection(0, 1); - $r3$.ɵtemplate(1, Cmp_ng_template_Template_1, 2, 0, "ng-template"); - $r3$.ɵtemplate(2, Cmp_ng_template_Template_2, 2, 0, "ng-template"); + $r3$.ɵtemplate(1, Cmp_ng_template_1_Template, 2, 0, "ng-template"); + $r3$.ɵtemplate(2, Cmp_ng_template_2_Template, 2, 0, "ng-template"); $r3$.ɵprojection(3, 2); - } + } } `; @@ -1911,7 +1911,7 @@ describe('compiler compliance', () => { const $c2$ = ["if", ""]; const $c3$ = ["baz", ""]; const $c4$ = ["bar", ""]; - function MyComponent_div_span_Template_2(rf, ctx) { + function MyComponent_div_3_span_2_Template(rf, ctx) { if (rf & 1) { $r3$.ɵelementStart(0, "span"); $r3$.ɵtext(1); @@ -1926,11 +1926,11 @@ describe('compiler compliance', () => { $r3$.ɵtextBinding(1, $r3$.ɵinterpolation3("", $foo$, "-", $bar$, "-", $baz$, "")); } } - function MyComponent_div_Template_3(rf, ctx) { + function MyComponent_div_3_Template(rf, ctx) { if (rf & 1) { $r3$.ɵelementStart(0, "div"); $r3$.ɵtext(1); - $r3$.ɵtemplate(2, MyComponent_div_span_Template_2, 2, 3, "span", $c2$); + $r3$.ɵtemplate(2, MyComponent_div_3_span_2_Template, 2, 3, "span", $c2$); $r3$.ɵelement(3, "span", null, $c4$); $r3$.ɵelementEnd(); } @@ -1952,7 +1952,7 @@ describe('compiler compliance', () => { if (rf & 1) { $r3$.ɵelement(0, "div", null, $c1$); $r3$.ɵtext(2); - $r3$.ɵtemplate(3, MyComponent_div_Template_3, 5, 2, "div", $c2$); + $r3$.ɵtemplate(3, MyComponent_div_3_Template, 5, 2, "div", $c2$); $r3$.ɵelement(4, "div", null, $c3$); } if (rf & 2) { @@ -2000,7 +2000,7 @@ describe('compiler compliance', () => { const $c1$ = ["foo", ""]; const $c2$ = [${AttributeMarker.SelectOnly}, "ngIf"]; - function MyComponent_div_span_Template_3(rf, ctx) { + function MyComponent_div_0_span_3_Template(rf, ctx) { if (rf & 1) { $i0$.ɵelementStart(0, "span"); $i0$.ɵtext(1); @@ -2013,11 +2013,11 @@ describe('compiler compliance', () => { } } - function MyComponent_div_Template_0(rf, ctx) { + function MyComponent_div_0_Template(rf, ctx) { if (rf & 1) { $i0$.ɵelementStart(0, "div"); $i0$.ɵelement(1, "div", null, $c1$); - $i0$.ɵtemplate(3, MyComponent_div_span_Template_3, 2, 2, "span", $c2$); + $i0$.ɵtemplate(3, MyComponent_div_0_span_3_Template, 2, 2, "span", $c2$); $i0$.ɵelementEnd(); } if (rf & 2) { @@ -2029,7 +2029,7 @@ describe('compiler compliance', () => { // ... template:function MyComponent_Template(rf, ctx){ if (rf & 1) { - $i0$.ɵtemplate(0, MyComponent_div_Template_0, 4, 1, "div", $c0$); + $i0$.ɵtemplate(0, MyComponent_div_0_Template, 4, 1, "div", $c0$); } if (rf & 2) { $i0$.ɵelementProperty(0, "ngForOf", $i0$.ɵbind(ctx.items)); @@ -2224,7 +2224,7 @@ describe('compiler compliance', () => { const MyComponentDefinition = ` const $t1_attrs$ = ["for", "", ${AttributeMarker.SelectOnly}, "forOf"]; - function MyComponent__svg_g_Template_1(rf, ctx) { + function MyComponent__svg_g_1_Template(rf, ctx) { if (rf & 1) { $r3$.ɵnamespaceSVG(); $r3$.ɵelementStart(0,"g"); @@ -2243,7 +2243,7 @@ describe('compiler compliance', () => { if (rf & 1) { $r3$.ɵnamespaceSVG(); $r3$.ɵelementStart(0,"svg"); - $r3$.ɵtemplate(1, MyComponent__svg_g_Template_1, 2, 0, ":svg:g", $t1_attrs$); + $r3$.ɵtemplate(1, MyComponent__svg_g_1_Template, 2, 0, ":svg:g", $t1_attrs$); $r3$.ɵelementEnd(); } if (rf & 2) { $r3$.ɵelementProperty(1,"forOf",$r3$.ɵbind(ctx.items)); } @@ -2300,7 +2300,7 @@ describe('compiler compliance', () => { const MyComponentDefinition = ` const $t1_attrs$ = ["for", "", ${AttributeMarker.SelectOnly}, "forOf"]; - function MyComponent_li_Template_1(rf, ctx) { + function MyComponent_li_1_Template(rf, ctx) { if (rf & 1) { $r3$.ɵelementStart(0, "li"); $r3$.ɵtext(1); @@ -2321,7 +2321,7 @@ describe('compiler compliance', () => { template: function MyComponent_Template(rf, ctx) { if (rf & 1) { $r3$.ɵelementStart(0, "ul"); - $r3$.ɵtemplate(1, MyComponent_li_Template_1, 2, 1, "li", $t1_attrs$); + $r3$.ɵtemplate(1, MyComponent_li_1_Template, 2, 1, "li", $t1_attrs$); $r3$.ɵelementEnd(); } if (rf & 2) { @@ -2380,7 +2380,7 @@ describe('compiler compliance', () => { const MyComponentDefinition = ` const $t4_attrs$ = ["for", "", ${AttributeMarker.SelectOnly}, "forOf"]; - function MyComponent_li_li_Template_4(rf, ctx) { + function MyComponent_li_1_li_4_Template(rf, ctx) { if (rf & 1) { $r3$.ɵelementStart(0, "li"); $r3$.ɵtext(1); @@ -2393,14 +2393,14 @@ describe('compiler compliance', () => { } } - function MyComponent_li_Template_1(rf, ctx) { + function MyComponent_li_1_Template(rf, ctx) { if (rf & 1) { $r3$.ɵelementStart(0, "li"); $r3$.ɵelementStart(1, "div"); $r3$.ɵtext(2); $r3$.ɵelementEnd(); $r3$.ɵelementStart(3, "ul"); - $r3$.ɵtemplate(4, MyComponent_li_li_Template_4, 2, 2, "li", $t4_attrs$); + $r3$.ɵtemplate(4, MyComponent_li_1_li_4_Template, 2, 2, "li", $t4_attrs$); $r3$.ɵelementEnd(); $r3$.ɵelementEnd(); } @@ -2421,7 +2421,7 @@ describe('compiler compliance', () => { template: function MyComponent_Template(rf, ctx) { if (rf & 1) { $r3$.ɵelementStart(0, "ul"); - $r3$.ɵtemplate(1, MyComponent_li_Template_1, 5, 2, "li", $c1$); + $r3$.ɵtemplate(1, MyComponent_li_1_Template, 5, 2, "li", $c1$); $r3$.ɵelementEnd(); } if (rf & 2) { diff --git a/packages/compiler-cli/test/compliance/r3_view_compiler_directives_spec.ts b/packages/compiler-cli/test/compliance/r3_view_compiler_directives_spec.ts index b9f96de301..45bf4feaa0 100644 --- a/packages/compiler-cli/test/compliance/r3_view_compiler_directives_spec.ts +++ b/packages/compiler-cli/test/compliance/r3_view_compiler_directives_spec.ts @@ -24,13 +24,13 @@ describe('compiler compliance: directives', () => { app: { 'spec.ts': ` import {Component, Directive, NgModule} from '@angular/core'; - + @Directive({selector: '[i18n]'}) export class I18nDirective {} - + @Component({selector: 'my-component', template: '
'}) export class MyComponent {} - + @NgModule({declarations: [I18nDirective, MyComponent]}) export class MyModule{}` } @@ -39,11 +39,11 @@ describe('compiler compliance: directives', () => { // MyComponent definition should be: const MyComponentDefinition = ` MyComponent.ngComponentDef = $r3$.ɵdefineComponent({ - type: MyComponent, - selectors: [["my-component"]], - factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); }, - consts: 1, - vars: 0, + type: MyComponent, + selectors: [["my-component"]], + factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); }, + consts: 1, + vars: 0, template: function MyComponent_Template(rf, ctx) { if (rf & 1) { $r3$.ɵelement(0, "div"); @@ -64,7 +64,7 @@ describe('compiler compliance: directives', () => { app: { 'spec.ts': ` import {Component, Directive, NgModule} from '@angular/core'; - + @Directive({selector: '[i18n]'}) export class I18nDirective {} @@ -73,10 +73,10 @@ describe('compiler compliance: directives', () => { @Directive({selector: '[foo]'}) export class FooDirective {} - + @Component({selector: 'my-component', template: '
'}) export class MyComponent {} - + @NgModule({declarations: [I18nDirective, I18nFooDirective, FooDirective, MyComponent]}) export class MyModule{}` } @@ -85,11 +85,11 @@ describe('compiler compliance: directives', () => { // MyComponent definition should be: const MyComponentDefinition = ` MyComponent.ngComponentDef = $r3$.ɵdefineComponent({ - type: MyComponent, - selectors: [["my-component"]], - factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); }, - consts: 1, - vars: 0, + type: MyComponent, + selectors: [["my-component"]], + factory: function MyComponent_Factory(t) { return new (t || MyComponent)(); }, + consts: 1, + vars: 0, template: function MyComponent_Template(rf, ctx) { if (rf & 1) { $r3$.ɵelement(0, "div"); @@ -111,15 +111,15 @@ describe('compiler compliance: directives', () => { app: { 'spec.ts': ` import {Component, Directive, Input, NgModule} from '@angular/core'; - + @Directive({selector: '[someDirective]'}) export class SomeDirective { @Input() someDirective; } - + @Component({selector: 'my-component', template: '
'}) export class MyComponent {} - + @NgModule({declarations: [SomeDirective, MyComponent]}) export class MyModule{} ` @@ -129,7 +129,7 @@ describe('compiler compliance: directives', () => { // MyComponent definition should be: const MyComponentDefinition = ` - … + … const _c0 = [${AttributeMarker.SelectOnly}, "someDirective"]; … MyComponent.ngComponentDef = $r3$.ɵdefineComponent({ @@ -184,7 +184,7 @@ describe('compiler compliance: directives', () => { const MyComponentDefinition = ` … const $_c0$ = ["directiveA", ""]; - function MyComponent_ng_template_Template_0(rf, ctx) { + function MyComponent_ng_template_0_Template(rf, ctx) { if (rf & 1) { $r3$.ɵtext(0, "Some content"); } @@ -194,7 +194,7 @@ describe('compiler compliance: directives', () => { … template: function MyComponent_Template(rf, ctx) { if (rf & 1) { - $r3$.ɵtemplate(0, MyComponent_ng_template_Template_0, 1, 0, "ng-template", $_c0$); + $r3$.ɵtemplate(0, MyComponent_ng_template_0_Template, 1, 0, "ng-template", $_c0$); } }, … @@ -238,7 +238,7 @@ describe('compiler compliance: directives', () => { … const $_c0$ = [${AttributeMarker.SelectOnly}, "ngIf"]; const $_c1$ = ["directiveA", ""]; - function MyComponent_ng_container_Template_0(rf, ctx) { + function MyComponent_ng_container_0_Template(rf, ctx) { if (rf & 1) { $r3$.ɵelementContainerStart(0, $_c1$); $r3$.ɵtext(1, "Some content"); @@ -250,7 +250,7 @@ describe('compiler compliance: directives', () => { … template: function MyComponent_Template(rf, ctx) { if (rf & 1) { - $r3$.ɵtemplate(0, MyComponent_ng_container_Template_0, 2, 0, "ng-container", $_c0$); + $r3$.ɵtemplate(0, MyComponent_ng_container_0_Template, 2, 0, "ng-container", $_c0$); } if (rf & 2) { $r3$.ɵelementProperty(0, "ngIf", $r3$.ɵbind(ctx.showing)); @@ -272,15 +272,15 @@ describe('compiler compliance: directives', () => { app: { 'spec.ts': ` import {Component, Directive, Input, NgModule} from '@angular/core'; - + @Directive({selector: '[someDirective]'}) export class SomeDirective { @Input() someDirective; } - + @Component({selector: 'my-component', template: ''}) export class MyComponent {} - + @NgModule({declarations: [SomeDirective, MyComponent]}) export class MyModule{} ` @@ -290,14 +290,14 @@ describe('compiler compliance: directives', () => { // MyComponent definition should be: const MyComponentDefinition = ` - … + … const $c0_a0$ = [${AttributeMarker.SelectOnly}, "someDirective"]; … MyComponent.ngComponentDef = $r3$.ɵdefineComponent({ … template: function MyComponent_Template(rf, ctx) { if (rf & 1) { - $r3$.ɵtemplate(0, MyComponent_ng_template_Template_0, 0, 0, "ng-template", $c0_a0$); + $r3$.ɵtemplate(0, MyComponent_ng_template_0_Template, 0, 0, "ng-template", $c0_a0$); } if (rf & 2) { $r3$.ɵelementProperty(0, "someDirective", $r3$.ɵbind(true)); @@ -321,15 +321,15 @@ describe('compiler compliance: directives', () => { app: { 'spec.ts': ` import {Component, Directive, Input, NgModule} from '@angular/core'; - + @Directive({selector: '[someDirective]'}) export class SomeDirective { @Input() someDirective; } - + @Component({selector: 'my-component', template: '
'}) export class MyComponent {} - + @NgModule({declarations: [SomeDirective, MyComponent]}) export class MyModule{} ` @@ -338,14 +338,14 @@ describe('compiler compliance: directives', () => { // MyComponent definition should be: const MyComponentDefinition = ` - … + … const $c0_a0$ = ["someDirective", ""]; … MyComponent.ngComponentDef = $r3$.ɵdefineComponent({ … template: function MyComponent_Template(rf, ctx) { if (rf & 1) { - $r3$.ɵtemplate(0, MyComponent_div_Template_0, 1, 0, "div", $c0_a0$); + $r3$.ɵtemplate(0, MyComponent_div_0_Template, 1, 0, "div", $c0_a0$); } }, … @@ -367,17 +367,17 @@ describe('compiler compliance: directives', () => { app: { 'spec.ts': ` import {Component, Directive, Output, EventEmitter, NgModule} from '@angular/core'; - + @Directive({selector: '[someDirective]'}) export class SomeDirective { @Output() someDirective = new EventEmitter(); } - + @Component({selector: 'my-component', template: '
'}) export class MyComponent { noop() {} } - + @NgModule({declarations: [SomeDirective, MyComponent]}) export class MyModule{} ` @@ -387,7 +387,7 @@ describe('compiler compliance: directives', () => { // MyComponent definition should be: const MyComponentDefinition = ` - … + … const $c0_a0$ = [${AttributeMarker.SelectOnly}, "someDirective"]; … MyComponent.ngComponentDef = $r3$.ɵdefineComponent({ @@ -395,7 +395,7 @@ describe('compiler compliance: directives', () => { template: function MyComponent_Template(rf, ctx) { if (rf & 1) { $r3$.ɵelementStart(0, "div", $c0_a0$); - $r3$.ɵlistener("someDirective", function MyComponent_Template_div_someDirective_listener($event) { return ctx.noop(); }); + $r3$.ɵlistener("someDirective", function MyComponent_Template_div_someDirective_0_listener($event) { return ctx.noop(); }); $r3$.ɵelementEnd(); } }, diff --git a/packages/compiler-cli/test/compliance/r3_view_compiler_i18n_spec.ts b/packages/compiler-cli/test/compliance/r3_view_compiler_i18n_spec.ts index 32d4232117..6e80d0c149 100644 --- a/packages/compiler-cli/test/compliance/r3_view_compiler_i18n_spec.ts +++ b/packages/compiler-cli/test/compliance/r3_view_compiler_i18n_spec.ts @@ -403,7 +403,7 @@ describe('i18n support in the view compiler', () => { "interpolation": "\uFFFD0\uFFFD" }); const $_c1$ = ["title", $MSG_EXTERNAL_8538466649243975456$$APP_SPEC_TS__1$]; - function MyComponent_div_Template_0(rf, ctx) { + function MyComponent_div_0_Template(rf, ctx) { if (rf & 1) { $r3$.ɵelementStart(0, "div"); $r3$.ɵelementStart(1, "div"); @@ -423,7 +423,7 @@ describe('i18n support in the view compiler', () => { vars: 1, template: function MyComponent_Template(rf, ctx) { if (rf & 1) { - $r3$.ɵtemplate(0, MyComponent_div_Template_0, 4, 3, "div", $_c0$); + $r3$.ɵtemplate(0, MyComponent_div_0_Template, 4, 3, "div", $_c0$); } if (rf & 2) { $r3$.ɵelementProperty(0, "ngForOf", $r3$.ɵbind(ctx.items)); @@ -532,7 +532,7 @@ describe('i18n support in the view compiler', () => { "interpolation": "\uFFFD0\uFFFD" }); const $_c1$ = ["title", $MSG_EXTERNAL_8538466649243975456$$APP_SPEC_TS__1$]; - function MyComponent_div_Template_0(rf, ctx) { + function MyComponent_div_0_Template(rf, ctx) { if (rf & 1) { $r3$.ɵelementStart(0, "div"); $r3$.ɵelementStart(1, "div"); @@ -552,7 +552,7 @@ describe('i18n support in the view compiler', () => { vars: 1, template: function MyComponent_Template(rf, ctx) { if (rf & 1) { - $r3$.ɵtemplate(0, MyComponent_div_Template_0, 4, 3, "div", $_c0$); + $r3$.ɵtemplate(0, MyComponent_div_0_Template, 4, 3, "div", $_c0$); } if (rf & 2) { $r3$.ɵelementProperty(0, "ngForOf", $r3$.ɵbind(ctx.items)); @@ -931,7 +931,7 @@ describe('i18n support in the view compiler', () => { "closeTagDiv": "\uFFFD/#3\uFFFD" }); … - function MyComponent_div_Template_2(rf, ctx) { + function MyComponent_div_2_Template(rf, ctx) { if (rf & 1) { $r3$.ɵelementStart(0, "div"); $r3$.ɵelementStart(1, "div"); @@ -956,7 +956,7 @@ describe('i18n support in the view compiler', () => { if (rf & 1) { $r3$.ɵelementStart(0, "div"); $r3$.ɵtext(1, " Some content "); - $r3$.ɵtemplate(2, MyComponent_div_Template_2, 5, 4, "div", $_c0$); + $r3$.ɵtemplate(2, MyComponent_div_2_Template, 5, 4, "div", $_c0$); $r3$.ɵelementEnd(); } if (rf & 2) { @@ -978,7 +978,7 @@ describe('i18n support in the view compiler', () => { const output = String.raw ` const $_c0$ = ["src", "logo.png"]; const $_c1$ = [${AttributeMarker.SelectOnly}, "ngIf"]; - function MyComponent_img_Template_1(rf, ctx) { + function MyComponent_img_1_Template(rf, ctx) { if (rf & 1) { $r3$.ɵelement(0, "img", $_c0$); } @@ -987,7 +987,7 @@ describe('i18n support in the view compiler', () => { "interpolation": "\uFFFD0\uFFFD" }); const $_c2$ = ["title", $MSG_EXTERNAL_2367729185105559721$]; - function MyComponent_img_Template_2(rf, ctx) { + function MyComponent_img_2_Template(rf, ctx) { if (rf & 1) { $r3$.ɵelementStart(0, "img", $_c0$); $r3$.ɵi18nAttributes(1, $_c2$); @@ -1005,8 +1005,8 @@ describe('i18n support in the view compiler', () => { template: function MyComponent_Template(rf, ctx) { if (rf & 1) { $r3$.ɵelement(0, "img", $_c0$); - $r3$.ɵtemplate(1, MyComponent_img_Template_1, 1, 0, "img", $_c1$); - $r3$.ɵtemplate(2, MyComponent_img_Template_2, 2, 1, "img", $_c1$); + $r3$.ɵtemplate(1, MyComponent_img_1_Template, 1, 0, "img", $_c1$); + $r3$.ɵtemplate(2, MyComponent_img_2_Template, 2, 1, "img", $_c1$); } if (rf & 2) { $r3$.ɵelementProperty(1, "ngIf", $r3$.ɵbind(ctx.visible)); @@ -1045,7 +1045,7 @@ describe('i18n support in the view compiler', () => { const output = String.raw ` const $_c0$ = [${AttributeMarker.SelectOnly}, "ngIf"]; - function MyComponent_div_div_Template_4(rf, ctx) { + function MyComponent_div_2_div_4_Template(rf, ctx) { if (rf & 1) { $r3$.ɵi18nStart(0, $I18N_EXTERNAL_1221890473527419724$$APP_SPEC_TS_0$, 2); $r3$.ɵelementStart(1, "div"); @@ -1060,13 +1060,13 @@ describe('i18n support in the view compiler', () => { $r3$.ɵi18nApply(0); } } - function MyComponent_div_Template_2(rf, ctx) { + function MyComponent_div_2_Template(rf, ctx) { if (rf & 1) { $r3$.ɵi18nStart(0, $I18N_EXTERNAL_1221890473527419724$$APP_SPEC_TS_0$, 1); $r3$.ɵelementStart(1, "div"); $r3$.ɵelementStart(2, "div"); $r3$.ɵpipe(3, "uppercase"); - $r3$.ɵtemplate(4, MyComponent_div_div_Template_4, 3, 2, "div", $_c1$); + $r3$.ɵtemplate(4, MyComponent_div_2_div_4_Template, 3, 2, "div", $_c1$); $r3$.ɵelementEnd(); $r3$.ɵelementEnd(); $r3$.ɵi18nEnd(); @@ -1093,7 +1093,7 @@ describe('i18n support in the view compiler', () => { "interpolation_5": "\uFFFD1:3\uFFFD" }); const $I18N_EXTERNAL_1221890473527419724$$APP_SPEC_TS_0$ = $r3$.ɵi18nPostprocess($MSG_EXTERNAL_1221890473527419724$$APP_SPEC_TS_0$); - function MyComponent_div_Template_3(rf, ctx) { + function MyComponent_div_3_Template(rf, ctx) { if (rf & 1) { $r3$.ɵi18nStart(0, $I18N_EXTERNAL_1221890473527419724$$APP_SPEC_TS_0$, 3); $r3$.ɵelementStart(1, "div"); @@ -1116,8 +1116,8 @@ describe('i18n support in the view compiler', () => { if (rf & 1) { $r3$.ɵelementStart(0, "div"); $r3$.ɵi18nStart(1, $I18N_EXTERNAL_1221890473527419724$$APP_SPEC_TS_0$); - $r3$.ɵtemplate(2, MyComponent_div_Template_2, 5, 5, "div", $_c1$); - $r3$.ɵtemplate(3, MyComponent_div_Template_3, 4, 4, "div", $_c1$); + $r3$.ɵtemplate(2, MyComponent_div_2_Template, 5, 5, "div", $_c1$); + $r3$.ɵtemplate(3, MyComponent_div_3_Template, 4, 4, "div", $_c1$); $r3$.ɵi18nEnd(); $r3$.ɵelementEnd(); } @@ -1144,7 +1144,7 @@ describe('i18n support in the view compiler', () => { "closeTagSpan": "\uFFFD/#2\uFFFD" }); … - function MyComponent_div_Template_0(rf, ctx) { + function MyComponent_div_0_Template(rf, ctx) { if (rf & 1) { $r3$.ɵelementStart(0, "div"); $r3$.ɵi18nStart(1, $MSG_EXTERNAL_119975189388320493$$APP_SPEC_TS__1$); @@ -1163,7 +1163,7 @@ describe('i18n support in the view compiler', () => { vars: 1, template: function MyComponent_Template(rf, ctx) { if (rf & 1) { - $r3$.ɵtemplate(0, MyComponent_div_Template_0, 3, 1, "div", $_c0$); + $r3$.ɵtemplate(0, MyComponent_div_0_Template, 3, 1, "div", $_c0$); } if (rf & 2) { $r3$.ɵelementProperty(0, "ngIf", $r3$.ɵbind(ctx.visible)); @@ -1234,7 +1234,7 @@ describe('i18n support in the view compiler', () => { const output = String.raw ` const $MSG_EXTERNAL_2413150872298537152$$APP_SPEC_TS_0$ = goog.getMsg("My i18n block #2"); const $MSG_EXTERNAL_4890179241114413722$$APP_SPEC_TS__1$ = goog.getMsg("My i18n block #1"); - function MyComponent_ng_template_Template_0(rf, ctx) { + function MyComponent_ng_template_0_Template(rf, ctx) { if (rf & 1) { $r3$.ɵi18n(0, $MSG_EXTERNAL_4890179241114413722$$APP_SPEC_TS__1$); } @@ -1242,7 +1242,7 @@ describe('i18n support in the view compiler', () => { … template: function MyComponent_Template(rf, ctx) { if (rf & 1) { - $r3$.ɵtemplate(0, MyComponent_ng_template_Template_0, 1, 0, "ng-template"); + $r3$.ɵtemplate(0, MyComponent_ng_template_0_Template, 1, 0, "ng-template"); $r3$.ɵelementContainerStart(1); $r3$.ɵi18n(2, $MSG_EXTERNAL_2413150872298537152$$APP_SPEC_TS_0$); $r3$.ɵelementContainerEnd(); @@ -1324,7 +1324,7 @@ describe('i18n support in the view compiler', () => { const $MSG_EXTERNAL_355394464191978948$$APP_SPEC_TS__0$ = goog.getMsg("Some content: {$interpolation}", { "interpolation": "\uFFFD0\uFFFD" }); - function MyComponent_ng_template_Template_0(rf, ctx) { + function MyComponent_ng_template_0_Template(rf, ctx) { if (rf & 1) { $r3$.ɵi18n(0, $MSG_EXTERNAL_355394464191978948$$APP_SPEC_TS__0$); $r3$.ɵpipe(1, "uppercase"); @@ -1339,7 +1339,7 @@ describe('i18n support in the view compiler', () => { vars: 0, template: function MyComponent_Template(rf, ctx) { if (rf & 1) { - $r3$.ɵtemplate(0, MyComponent_ng_template_Template_0, 2, 3, "ng-template"); + $r3$.ɵtemplate(0, MyComponent_ng_template_0_Template, 2, 3, "ng-template"); } } `; @@ -1364,7 +1364,7 @@ describe('i18n support in the view compiler', () => { "closeTagNgContainer": "\uFFFD/#3\uFFFD", "interpolation": "\uFFFD0:1\uFFFD" }); - function MyComponent_ng_template_Template_2(rf, ctx) { + function MyComponent_ng_template_2_Template(rf, ctx) { if (rf & 1) { $r3$.ɵi18n(0, $MSG_EXTERNAL_702706566400598764$$APP_SPEC_TS_0$, 1); $r3$.ɵpipe(1, "uppercase"); @@ -1382,7 +1382,7 @@ describe('i18n support in the view compiler', () => { if (rf & 1) { $r3$.ɵelementStart(0, "div"); $r3$.ɵi18nStart(1, $MSG_EXTERNAL_702706566400598764$$APP_SPEC_TS_0$); - $r3$.ɵtemplate(2, MyComponent_ng_template_Template_2, 2, 3, "ng-template"); + $r3$.ɵtemplate(2, MyComponent_ng_template_2_Template, 2, 3, "ng-template"); $r3$.ɵelementContainerStart(3); $r3$.ɵpipe(4, "uppercase"); $r3$.ɵelementContainerEnd(); @@ -1414,7 +1414,7 @@ describe('i18n support in the view compiler', () => { const $I18N_EXTERNAL_7842238767399919809$$APP_SPEC_TS__1$ = $r3$.ɵi18nPostprocess($MSG_EXTERNAL_7842238767399919809$$APP_SPEC_TS__1$, { "VAR_SELECT": "\uFFFD0\uFFFD" }); - function MyComponent_ng_template_Template_0(rf, ctx) { + function MyComponent_ng_template_0_Template(rf, ctx) { if (rf & 1) { $r3$.ɵi18n(0, $I18N_EXTERNAL_7842238767399919809$$APP_SPEC_TS__1$); } @@ -1429,7 +1429,7 @@ describe('i18n support in the view compiler', () => { vars: 1, template: function MyComponent_Template(rf, ctx) { if (rf & 1) { - $r3$.ɵtemplate(0, MyComponent_ng_template_Template_0, 1, 1, "ng-template"); + $r3$.ɵtemplate(0, MyComponent_ng_template_0_Template, 1, 1, "ng-template"); $r3$.ɵelementContainerStart(1); $r3$.ɵi18n(2, $I18N_EXTERNAL_8806993169187953163$$APP_SPEC_TS_0$); $r3$.ɵelementContainerEnd(); @@ -1460,7 +1460,7 @@ describe('i18n support in the view compiler', () => { `; const output = String.raw ` - function MyComponent_ng_template_ng_template_ng_template_Template_1(rf, ctx) { + function MyComponent_ng_template_2_ng_template_2_ng_template_1_Template(rf, ctx) { if (rf & 1) { $r3$.ɵi18n(0, $I18N_EXTERNAL_2051477021417799640$$APP_SPEC_TS_0$, 3); } @@ -1470,10 +1470,10 @@ describe('i18n support in the view compiler', () => { $r3$.ɵi18nApply(0); } } - function MyComponent_ng_template_ng_template_Template_2(rf, ctx) { + function MyComponent_ng_template_2_ng_template_2_Template(rf, ctx) { if (rf & 1) { $r3$.ɵi18nStart(0, $I18N_EXTERNAL_2051477021417799640$$APP_SPEC_TS_0$, 2); - $r3$.ɵtemplate(1, MyComponent_ng_template_ng_template_ng_template_Template_1, 1, 1, "ng-template"); + $r3$.ɵtemplate(1, MyComponent_ng_template_2_ng_template_2_ng_template_1_Template, 1, 1, "ng-template"); $r3$.ɵi18nEnd(); } if (rf & 2) { @@ -1490,11 +1490,11 @@ describe('i18n support in the view compiler', () => { "interpolation_2": "\uFFFD0:3\uFFFD" }); const $I18N_EXTERNAL_2051477021417799640$$APP_SPEC_TS_0$ = $r3$.ɵi18nPostprocess($MSG_EXTERNAL_2051477021417799640$$APP_SPEC_TS_0$); - function MyComponent_ng_template_Template_2(rf, ctx) { + function MyComponent_ng_template_2_Template(rf, ctx) { if (rf & 1) { $r3$.ɵi18nStart(0, $I18N_EXTERNAL_2051477021417799640$$APP_SPEC_TS_0$, 1); $r3$.ɵpipe(1, "uppercase"); - $r3$.ɵtemplate(2, MyComponent_ng_template_ng_template_Template_2, 2, 1, "ng-template"); + $r3$.ɵtemplate(2, MyComponent_ng_template_2_ng_template_2_Template, 2, 1, "ng-template"); $r3$.ɵi18nEnd(); } if (rf & 2) { @@ -1510,7 +1510,7 @@ describe('i18n support in the view compiler', () => { if (rf & 1) { $r3$.ɵelementStart(0, "div"); $r3$.ɵi18nStart(1, $I18N_EXTERNAL_2051477021417799640$$APP_SPEC_TS_0$); - $r3$.ɵtemplate(2, MyComponent_ng_template_Template_2, 3, 3, "ng-template"); + $r3$.ɵtemplate(2, MyComponent_ng_template_2_Template, 3, 3, "ng-template"); $r3$.ɵi18nEnd(); $r3$.ɵelementEnd(); } @@ -1535,7 +1535,7 @@ describe('i18n support in the view compiler', () => { const $I18N_EXTERNAL_8806993169187953163$$APP_SPEC_TS__1$ = $r3$.ɵi18nPostprocess($MSG_EXTERNAL_8806993169187953163$$APP_SPEC_TS__1$, { "VAR_SELECT": "\uFFFD0\uFFFD" }); - function MyComponent_ng_template_Template_2(rf, ctx) { + function MyComponent_ng_template_2_Template(rf, ctx) { if (rf & 1) { $r3$.ɵi18n(0, $I18N_EXTERNAL_8806993169187953163$$APP_SPEC_TS__1$); } @@ -1553,7 +1553,7 @@ describe('i18n support in the view compiler', () => { $r3$.ɵelementContainerStart(0); $r3$.ɵi18n(1, $I18N_EXTERNAL_7842238767399919809$$APP_SPEC_TS_0$); $r3$.ɵelementContainerEnd(); - $r3$.ɵtemplate(2, MyComponent_ng_template_Template_2, 1, 1, "ng-template"); + $r3$.ɵtemplate(2, MyComponent_ng_template_2_Template, 1, 1, "ng-template"); } if (rf & 2) { $r3$.ɵi18nExp($r3$.ɵbind(ctx.gender)); @@ -1583,7 +1583,7 @@ describe('i18n support in the view compiler', () => { const $MSG_EXTERNAL_461986953980355147$$APP_SPEC_TS__2$ = goog.getMsg("{$tagImg} is my logo #2 ", { "tagImg": "\uFFFD#1\uFFFD\uFFFD/#1\uFFFD" }); - function MyComponent_ng_template_Template_3(rf, ctx) { + function MyComponent_ng_template_3_Template(rf, ctx) { if (rf & 1) { $r3$.ɵi18nStart(0, $MSG_EXTERNAL_461986953980355147$$APP_SPEC_TS__2$); $r3$.ɵelement(1, "img", $_c0$); @@ -1598,7 +1598,7 @@ describe('i18n support in the view compiler', () => { $r3$.ɵelement(2, "img", $_c0$); $r3$.ɵi18nEnd(); $r3$.ɵelementContainerEnd(); - $r3$.ɵtemplate(3, MyComponent_ng_template_Template_3, 2, 0, "ng-template"); + $r3$.ɵtemplate(3, MyComponent_ng_template_3_Template, 2, 0, "ng-template"); } } `; @@ -1706,7 +1706,7 @@ describe('i18n support in the view compiler', () => { const $I18N_EXTERNAL_8806993169187953163$$APP_SPEC_TS__3$ = $r3$.ɵi18nPostprocess($MSG_EXTERNAL_8806993169187953163$$APP_SPEC_TS__3$, { "VAR_SELECT": "\uFFFD0\uFFFD" }); - function MyComponent_div_Template_2(rf, ctx) { + function MyComponent_div_2_Template(rf, ctx) { if (rf & 1) { $r3$.ɵelementStart(0, "div", $_c1$); $r3$.ɵi18n(1, $I18N_EXTERNAL_8806993169187953163$$APP_SPEC_TS__3$); @@ -1725,7 +1725,7 @@ describe('i18n support in the view compiler', () => { const $I18N_EXTERNAL_1922743304863699161$$APP_SPEC_TS__5$ = $r3$.ɵi18nPostprocess($MSG_EXTERNAL_1922743304863699161$$APP_SPEC_TS__5$, { "VAR_SELECT": "\uFFFD0\uFFFD" }); - function MyComponent_div_Template_3(rf, ctx) { + function MyComponent_div_3_Template(rf, ctx) { if (rf & 1) { $r3$.ɵelementStart(0, "div", $_c2$); $r3$.ɵtext(1, " You have "); @@ -1748,8 +1748,8 @@ describe('i18n support in the view compiler', () => { $r3$.ɵelementStart(0, "div"); $r3$.ɵi18n(1, $I18N_EXTERNAL_7842238767399919809$$APP_SPEC_TS_0$); $r3$.ɵelementEnd(); - $r3$.ɵtemplate(2, MyComponent_div_Template_2, 2, 1, "div", $_c0$); - $r3$.ɵtemplate(3, MyComponent_div_Template_3, 4, 2, "div", $_c0$); + $r3$.ɵtemplate(2, MyComponent_div_2_Template, 2, 1, "div", $_c0$); + $r3$.ɵtemplate(3, MyComponent_div_3_Template, 4, 2, "div", $_c0$); } if (rf & 2) { $r3$.ɵi18nExp($r3$.ɵbind(ctx.gender)); @@ -1955,7 +1955,7 @@ describe('i18n support in the view compiler', () => { const $I18N_APP_SPEC_TS_0$ = $r3$.ɵi18nPostprocess($MSG_APP_SPEC_TS_0$, { "ICU": [$I18N_APP_SPEC_TS_1$, $I18N_APP_SPEC_TS_2$, $I18N_APP_SPEC_TS__4$] }); - function MyComponent_div_Template_3(rf, ctx) { + function MyComponent_div_3_Template(rf, ctx) { if (rf & 1) { $r3$.ɵi18nStart(0, $I18N_APP_SPEC_TS_0$, 1); $r3$.ɵelement(1, "div"); @@ -1975,7 +1975,7 @@ describe('i18n support in the view compiler', () => { $r3$.ɵelementStart(0, "div"); $r3$.ɵi18nStart(1, $I18N_APP_SPEC_TS_0$); $r3$.ɵelement(2, "div"); - $r3$.ɵtemplate(3, MyComponent_div_Template_3, 2, 1, "div", $_c3$); + $r3$.ɵtemplate(3, MyComponent_div_3_Template, 2, 1, "div", $_c3$); $r3$.ɵi18nEnd(); $r3$.ɵelementEnd(); } @@ -2060,7 +2060,7 @@ describe('i18n support in the view compiler', () => { "icu": $I18N_EXTERNAL_7842238767399919809$$APP_SPEC_TS_1$, "icu_1": $I18N_EXTERNAL_7068143081688428291$$APP_SPEC_TS__3$ }); - function MyComponent_span_Template_2(rf, ctx) { + function MyComponent_span_2_Template(rf, ctx) { if (rf & 1) { $r3$.ɵi18nStart(0, $MSG_EXTERNAL_1194472282609532229$$APP_SPEC_TS_0$, 1); $r3$.ɵelement(1, "span"); @@ -2079,7 +2079,7 @@ describe('i18n support in the view compiler', () => { if (rf & 1) { $r3$.ɵelementStart(0, "div"); $r3$.ɵi18nStart(1, $MSG_EXTERNAL_1194472282609532229$$APP_SPEC_TS_0$); - $r3$.ɵtemplate(2, MyComponent_span_Template_2, 2, 1, "span", $_c2$); + $r3$.ɵtemplate(2, MyComponent_span_2_Template, 2, 1, "span", $_c2$); $r3$.ɵi18nEnd(); $r3$.ɵelementEnd(); } @@ -2125,7 +2125,7 @@ describe('i18n support in the view compiler', () => { "icu": $I18N_EXTERNAL_7825031864601787094$$APP_SPEC_TS_1$, "icu_1": $I18N_EXTERNAL_2310343208266678305$$APP_SPEC_TS__3$ }); - function MyComponent_span_Template_2(rf, ctx) { + function MyComponent_span_2_Template(rf, ctx) { if (rf & 1) { $r3$.ɵi18nStart(0, $MSG_EXTERNAL_7186042105600518133$$APP_SPEC_TS_0$, 1); $r3$.ɵelement(1, "span"); @@ -2145,7 +2145,7 @@ describe('i18n support in the view compiler', () => { if (rf & 1) { $r3$.ɵelementStart(0, "div"); $r3$.ɵi18nStart(1, $MSG_EXTERNAL_7186042105600518133$$APP_SPEC_TS_0$); - $r3$.ɵtemplate(2, MyComponent_span_Template_2, 2, 2, "span", $_c2$); + $r3$.ɵtemplate(2, MyComponent_span_2_Template, 2, 2, "span", $_c2$); $r3$.ɵi18nEnd(); $r3$.ɵelementEnd(); } diff --git a/packages/compiler-cli/test/compliance/r3_view_compiler_listener_spec.ts b/packages/compiler-cli/test/compliance/r3_view_compiler_listener_spec.ts index e8c993e387..207a0e2cb6 100644 --- a/packages/compiler-cli/test/compliance/r3_view_compiler_listener_spec.ts +++ b/packages/compiler-cli/test/compliance/r3_view_compiler_listener_spec.ts @@ -46,7 +46,7 @@ describe('compiler compliance: listen()', () => { template: function MyComponent_Template(rf, ctx) { if (rf & 1) { $r3$.ɵelementStart(0, "div", $e0_attrs$); - $r3$.ɵlistener("click", function MyComponent_Template_div_click_listener($event) { + $r3$.ɵlistener("click", function MyComponent_Template_div_click_0_listener($event) { ctx.onClick($event); return (1 == 2); }); @@ -92,7 +92,7 @@ describe('compiler compliance: listen()', () => { template: function MyComponent_Template(rf, ctx) { if (rf & 1) { $r3$.ɵelementStart(0, "my-app", $e0_attrs$); - $r3$.ɵlistener("click", function MyComponent_Template_my_app_click_listener($event) { + $r3$.ɵlistener("click", function MyComponent_Template_my_app_click_0_listener($event) { return ctx.onClick($event); }); $r3$.ɵelementEnd(); @@ -136,19 +136,19 @@ describe('compiler compliance: listen()', () => { const $t0_attrs$ = [${AttributeMarker.SelectOnly}, "ngIf"]; const $e_attrs$ = [${AttributeMarker.SelectOnly}, "click"]; - function MyComponent_div_Template_0(rf, ctx) { + function MyComponent_div_0_Template(rf, ctx) { if (rf & 1) { const $s$ = $r3$.ɵgetCurrentView(); $r3$.ɵelementStart(0, "div"); $r3$.ɵelementStart(1, "div", $e_attrs$); - $r3$.ɵlistener("click", function MyComponent_div_Template_0_div_click_listener($event) { + $r3$.ɵlistener("click", function MyComponent_div_0_Template_div_click_1_listener($event) { $r3$.ɵrestoreView($s$); const $comp$ = $r3$.ɵnextContext(); return $comp$.onClick($comp$.foo); }); $r3$.ɵelementEnd(); $r3$.ɵelementStart(2, "button", $e_attrs$); - $r3$.ɵlistener("click", function MyComponent_div_Template_0_button_click_listener($event) { + $r3$.ɵlistener("click", function MyComponent_div_0_Template_button_click_2_listener($event) { $r3$.ɵrestoreView($s$); const $comp2$ = $r3$.ɵnextContext(); return $comp2$.onClick2($comp2$.bar); @@ -160,7 +160,7 @@ describe('compiler compliance: listen()', () => { // ... template: function MyComponent_Template(rf, ctx) { if (rf & 1) { - $r3$.ɵtemplate(0, MyComponent_div_Template_0, 3, 0, "div", $c0$); + $r3$.ɵtemplate(0, MyComponent_div_0_Template, 3, 0, "div", $c0$); } if (rf & 2) { $i0$.ɵelementProperty(0, "ngIf", $i0$.ɵbind(ctx.showing)); @@ -208,7 +208,7 @@ describe('compiler compliance: listen()', () => { if (rf & 1) { const $s$ = $r3$.ɵgetCurrentView(); $r3$.ɵelementStart(0, "button", $e0_attrs$); - $r3$.ɵlistener("click", function MyComponent_Template_button_click_listener($event) { + $r3$.ɵlistener("click", function MyComponent_Template_button_click_0_listener($event) { $r3$.ɵrestoreView($s$); const $user$ = $r3$.ɵreference(3); return ctx.onClick($user$.value); diff --git a/packages/compiler-cli/test/compliance/r3_view_compiler_styling_spec.ts b/packages/compiler-cli/test/compliance/r3_view_compiler_styling_spec.ts index 9a99dc7f98..a27da6d1fe 100644 --- a/packages/compiler-cli/test/compliance/r3_view_compiler_styling_spec.ts +++ b/packages/compiler-cli/test/compliance/r3_view_compiler_styling_spec.ts @@ -281,8 +281,8 @@ describe('compiler compliance: styling', () => { template: function MyComponent_Template(rf, ctx) { if (rf & 1) { $r3$.ɵelementStart(0, "div", _c0); - $r3$.ɵlistener("@myAnimation.start", function MyComponent_Template_div__myAnimation_start_listener($event) { return ctx.onStart($event); }); - $r3$.ɵlistener("@myAnimation.done", function MyComponent_Template_div__myAnimation_done_listener($event) { return ctx.onDone($event); }); + $r3$.ɵlistener("@myAnimation.start", function MyComponent_Template_div__myAnimation_start_0_listener($event) { return ctx.onStart($event); }); + $r3$.ɵlistener("@myAnimation.done", function MyComponent_Template_div__myAnimation_done_0_listener($event) { return ctx.onDone($event); }); $r3$.ɵelementEnd(); } if (rf & 2) { $r3$.ɵelementProperty(0, "@myAnimation", $r3$.ɵbind(ctx.exp)); diff --git a/packages/compiler-cli/test/compliance/r3_view_compiler_template_spec.ts b/packages/compiler-cli/test/compliance/r3_view_compiler_template_spec.ts index d7ebaf48a0..75e2a2c000 100644 --- a/packages/compiler-cli/test/compliance/r3_view_compiler_template_spec.ts +++ b/packages/compiler-cli/test/compliance/r3_view_compiler_template_spec.ts @@ -52,12 +52,12 @@ describe('compiler compliance: template', () => { const template = ` const $c0$ = ["ngFor", "", ${AttributeMarker.SelectOnly}, "ngForOf"]; const $e0_attrs$ = [${AttributeMarker.SelectOnly}, "title", "click"]; - function MyComponent_ul_li_div_Template_1(rf, ctx) { + function MyComponent_ul_0_li_1_div_1_Template(rf, ctx) { if (rf & 1) { const $s$ = $i0$.ɵgetCurrentView(); $i0$.ɵelementStart(0, "div", $e0_attrs$); - $i0$.ɵlistener("click", function MyComponent_ul_li_div_Template_1_div_click_listener($event){ + $i0$.ɵlistener("click", function MyComponent_ul_0_li_1_div_1_Template_div_click_0_listener($event){ $i0$.ɵrestoreView($s$); const $inner$ = ctx.$implicit; const $middle$ = $i0$.ɵnextContext().$implicit; @@ -79,10 +79,10 @@ describe('compiler compliance: template', () => { } } - function MyComponent_ul_li_Template_1(rf, ctx) { + function MyComponent_ul_0_li_1_Template(rf, ctx) { if (rf & 1) { $i0$.ɵelementStart(0, "li"); - $i0$.ɵtemplate(1, MyComponent_ul_li_div_Template_1, 2, 2, "div", _c0); + $i0$.ɵtemplate(1, MyComponent_ul_0_li_1_div_1_Template, 2, 2, "div", _c0); $i0$.ɵelementEnd(); } if (rf & 2) { @@ -91,10 +91,10 @@ describe('compiler compliance: template', () => { } } - function MyComponent_ul_Template_0(rf, ctx) { + function MyComponent_ul_0_Template(rf, ctx) { if (rf & 1) { $i0$.ɵelementStart(0, "ul"); - $i0$.ɵtemplate(1, MyComponent_ul_li_Template_1, 2, 1, "li", _c0); + $i0$.ɵtemplate(1, MyComponent_ul_0_li_1_Template, 2, 1, "li", _c0); $i0$.ɵelementEnd(); } if (rf & 2) { @@ -105,7 +105,7 @@ describe('compiler compliance: template', () => { // ... template:function MyComponent_Template(rf, ctx){ if (rf & 1) { - $i0$.ɵtemplate(0, MyComponent_ul_Template_0, 2, 1, "ul", _c0); + $i0$.ɵtemplate(0, MyComponent_ul_0_Template, 2, 1, "ul", _c0); } if (rf & 2) { $i0$.ɵelementProperty(0, "ngForOf", $i0$.ɵbind(ctx.items)); @@ -141,7 +141,7 @@ describe('compiler compliance: template', () => { const template = ` const $c0$ = ["ngFor", "", ${AttributeMarker.SelectOnly}, "ngForOf"]; - function MyComponent_span_Template_0(rf, ctx) { + function MyComponent_span_0_Template(rf, ctx) { if (rf & 1) { $i0$.ɵelementStart(0, "span"); $i0$.ɵtext(1); @@ -156,7 +156,7 @@ describe('compiler compliance: template', () => { // ... template:function MyComponent_Template(rf, ctx){ if (rf & 1) { - $i0$.ɵtemplate(0, MyComponent_span_Template_0, 2, 2, "span", _c0); + $i0$.ɵtemplate(0, MyComponent_span_0_Template, 2, 2, "span", _c0); } if (rf & 2) { $i0$.ɵelementProperty(0, "ngForOf", $i0$.ɵbind(ctx.items)); @@ -195,7 +195,7 @@ describe('compiler compliance: template', () => { const $c0$ = ["ngFor", "", ${AttributeMarker.SelectOnly}, "ngForOf"]; const $c1$ = [${AttributeMarker.SelectOnly}, "ngIf"]; - function MyComponent_div_span_Template_1(rf, ctx) { + function MyComponent_div_0_span_1_Template(rf, ctx) { if (rf & 1) { $i0$.ɵelementStart(0, "span"); $i0$.ɵtext(1); @@ -209,10 +209,10 @@ describe('compiler compliance: template', () => { } } - function MyComponent_div_Template_0(rf, ctx) { + function MyComponent_div_0_Template(rf, ctx) { if (rf & 1) { $i0$.ɵelementStart(0, "div"); - $i0$.ɵtemplate(1, MyComponent_div_span_Template_1, 2, 2, "span", $c1$); + $i0$.ɵtemplate(1, MyComponent_div_0_span_1_Template, 2, 2, "span", $c1$); $i0$.ɵelementEnd(); } if (rf & 2) { @@ -224,7 +224,7 @@ describe('compiler compliance: template', () => { // ... template:function MyComponent_Template(rf, ctx){ if (rf & 1) { - $i0$.ɵtemplate(0, MyComponent_div_Template_0, 2, 1, "div", $c0$); + $i0$.ɵtemplate(0, MyComponent_div_0_Template, 2, 1, "div", $c0$); } if (rf & 2) { $i0$.ɵelementProperty(0, "ngForOf", $i0$.ɵbind(ctx.items)); @@ -264,7 +264,7 @@ describe('compiler compliance: template', () => { // The template should look like this (where IDENT is a wild card for an identifier): const template = ` const $c0$ = ["ngFor", "", ${AttributeMarker.SelectOnly}, "ngForOf"]; - function MyComponent_div_div_div_Template_1(rf, ctx) { + function MyComponent_div_0_div_1_div_1_Template(rf, ctx) { if (rf & 1) { $i0$.ɵelementStart(0, "div"); $i0$.ɵtext(1); @@ -277,10 +277,10 @@ describe('compiler compliance: template', () => { } } - function MyComponent_div_div_Template_1(rf, ctx) { + function MyComponent_div_0_div_1_Template(rf, ctx) { if (rf & 1) { $i0$.ɵelementStart(0, "div"); - $i0$.ɵtemplate(1, MyComponent_div_div_div_Template_1, 2, 2, "div", _c0); + $i0$.ɵtemplate(1, MyComponent_div_0_div_1_div_1_Template, 2, 2, "div", _c0); $i0$.ɵelementEnd(); } if (rf & 2) { @@ -289,10 +289,10 @@ describe('compiler compliance: template', () => { } } - function MyComponent_div_Template_0(rf, ctx) { + function MyComponent_div_0_Template(rf, ctx) { if (rf & 1) { $i0$.ɵelementStart(0, "div"); - $i0$.ɵtemplate(1, MyComponent_div_div_Template_1, 2, 1, "div", _c0); + $i0$.ɵtemplate(1, MyComponent_div_0_div_1_Template, 2, 1, "div", _c0); $i0$.ɵelementEnd(); } if (rf & 2) { @@ -303,7 +303,7 @@ describe('compiler compliance: template', () => { // ... template:function MyComponent_Template(rf, ctx){ if (rf & 1) { - $i0$.ɵtemplate(0, MyComponent_div_Template_0, 2, 1, "div", _c0); + $i0$.ɵtemplate(0, MyComponent_div_0_Template, 2, 1, "div", _c0); } if (rf & 2) { $i0$.ɵelementProperty(0, "ngForOf", $i0$.ɵbind(ctx.items)); @@ -339,7 +339,7 @@ describe('compiler compliance: template', () => { const template = ` const $c0$ = ["attr", "l", ${AttributeMarker.SelectOnly}, "boundAttr"]; - function MyComponent_ng_template_Template_0(rf, ctx) { + function MyComponent_ng_template_0_Template(rf, ctx) { if (rf & 1) { $i0$.ɵtext(0, " some-content "); } @@ -349,7 +349,7 @@ describe('compiler compliance: template', () => { template: function MyComponent_Template(rf, ctx) { if (rf & 1) { - $i0$.ɵtemplate(0, MyComponent_ng_template_Template_0, 1, 0, "ng-template", $c0$); + $i0$.ɵtemplate(0, MyComponent_ng_template_0_Template, 1, 0, "ng-template", $c0$); } if (rf & 2) { $i0$.ɵelementProperty(0, "boundAttr", $i0$.ɵbind(ctx.b)); @@ -370,7 +370,7 @@ describe('compiler compliance: template', () => { @Component({ selector: 'my-component', - template: 'some-content'; + template: 'some-content', }) export class MyComponent {} @@ -383,7 +383,7 @@ describe('compiler compliance: template', () => { const template = ` const $t0_refs$ = ["foo", ""]; - function MyComponent_ng_template_Template_0(rf, ctx) { + function MyComponent_ng_template_0_Template(rf, ctx) { if (rf & 1) { $i0$.ɵtext(0, "some-content"); } @@ -393,7 +393,7 @@ describe('compiler compliance: template', () => { template: function MyComponent_Template(rf, ctx) { if (rf & 1) { - $i0$.ɵtemplate(0, MyComponent_ng_template_Template_0, 1, 0, "ng-template", null, $t0_refs$, $i0$.ɵtemplateRefExtractor); + $i0$.ɵtemplate(0, MyComponent_ng_template_0_Template, 1, 0, "ng-template", null, $t0_refs$, $i0$.ɵtemplateRefExtractor); } }`; @@ -411,7 +411,7 @@ describe('compiler compliance: template', () => { @Component({ selector: 'my-component', - template: ''; + template: '', }) export class MyComponent {} @@ -424,14 +424,14 @@ describe('compiler compliance: template', () => { const template = ` const $t0_attrs$ = [${AttributeMarker.SelectOnly}, "outDirective"]; - function MyComponent_ng_template_Template_0(rf, ctx) { } + function MyComponent_ng_template_0_Template(rf, ctx) { } // ... template: function MyComponent_Template(rf, ctx) { if (rf & 1) { - $i0$.ɵtemplate(0, MyComponent_ng_template_Template_0, 0, 0, "ng-template", $t0_attrs$); - $i0$.ɵlistener("outDirective", function MyComponent_Template_ng_template_outDirective_listener($event) { return $event.doSth(); }); + $i0$.ɵtemplate(0, MyComponent_ng_template_0_Template, 0, 0, "ng-template", $t0_attrs$); + $i0$.ɵlistener("outDirective", function MyComponent_Template_ng_template_outDirective_0_listener($event) { return $event.doSth(); }); } }`; @@ -440,4 +440,122 @@ describe('compiler compliance: template', () => { expectEmit(result.source, template, 'Incorrect template'); }); + + it('should create unique template function names even for similar nested template structures', + () => { + const files = { + app: { + 'spec1.ts': ` + import {Component, NgModule} from '@angular/core'; + + @Component({ + selector: 'a-component', + template: \` +
+

less than 10

+

less than 10

+
+
+

more than 10

+
+ \`, + }) + export class AComponent { + items = [4, 2]; + } + + @NgModule({declarations: [AComponent]}) + export class AModule {} + `, + 'spec2.ts': ` + import {Component, NgModule} from '@angular/core'; + + @Component({ + selector: 'b-component', + template: \` +
+ +

less than 10

+

less than 10

+
+ +

less than 10

+
+
+
+ +

more than 10

+
+
+ \`, + }) + export class BComponent { + items = [ + {subitems: [1, 3]}, + {subitems: [3, 7]}, + ]; + } + + @NgModule({declarations: [BComponent]}) + export class BModule {} + `, + }, + }; + + const result = compile(files, angularFiles); + + const allTemplateFunctionsNames = (result.source.match(/function ([^\s(]+)/g) || []) + .map(x => x.slice(9)) + .filter(x => x.includes('Template')) + .sort(); + const uniqueTemplateFunctionNames = Array.from(new Set(allTemplateFunctionsNames)); + + // Expected template function: + // - 5 for AComponent's template. + // - 9 for BComponent's template. + // - 2 for the two components. + expect(allTemplateFunctionsNames.length).toBe(5 + 9 + 2); + expect(allTemplateFunctionsNames).toEqual(uniqueTemplateFunctionNames); + }); + + it('should create unique listener function names even for similar nested template structures', + () => { + const files = { + app: { + 'spec.ts': ` + import {Component, NgModule} from '@angular/core'; + + @Component({ + selector: 'my-component', + template: \` +
+

{{ item }}

+

{{ item }}

+
+
+

{{ item }}

+
+ \`, + }) + export class MyComponent { + items = [4, 2]; + } + + @NgModule({declarations: [MyComponent]}) + export class MyModule {} + `, + }, + }; + + const result = compile(files, angularFiles); + + const allListenerFunctionsNames = (result.source.match(/function ([^\s(]+)/g) || []) + .map(x => x.slice(9)) + .filter(x => x.includes('listener')) + .sort(); + const uniqueListenerFunctionNames = Array.from(new Set(allListenerFunctionsNames)); + + expect(allListenerFunctionsNames.length).toBe(3); + expect(allListenerFunctionsNames).toEqual(uniqueListenerFunctionNames); + }); }); diff --git a/packages/compiler/src/render3/view/template.ts b/packages/compiler/src/render3/view/template.ts index 1638fca83e..ebe5a834ab 100644 --- a/packages/compiler/src/render3/view/template.ts +++ b/packages/compiler/src/render3/view/template.ts @@ -632,7 +632,7 @@ export class TemplateDefinitionBuilder implements t.Visitor, LocalResolver element.outputs.forEach((outputAst: t.BoundEvent) => { this.creationInstruction( outputAst.sourceSpan, R3.listener, - this.prepareListenerParameter(element.name, outputAst)); + this.prepareListenerParameter(element.name, outputAst, elementIndex)); }); } @@ -707,9 +707,8 @@ export class TemplateDefinitionBuilder implements t.Visitor, LocalResolver } const tagName = sanitizeIdentifier(template.tagName || ''); - const contextName = tagName ? `${this.contextName}_${tagName}` : ''; - const templateName = - contextName ? `${contextName}_Template_${templateIndex}` : `Template_${templateIndex}`; + const contextName = `${tagName ? this.contextName + '_' + tagName : ''}_${templateIndex}`; + const templateName = `${contextName}_Template`; const parameters: o.Expression[] = [ o.literal(templateIndex), @@ -780,7 +779,7 @@ export class TemplateDefinitionBuilder implements t.Visitor, LocalResolver template.outputs.forEach((outputAst: t.BoundEvent) => { this.creationInstruction( outputAst.sourceSpan, R3.listener, - this.prepareListenerParameter('ng_template', outputAst)); + this.prepareListenerParameter('ng_template', outputAst, templateIndex)); }); } @@ -1062,14 +1061,16 @@ export class TemplateDefinitionBuilder implements t.Visitor, LocalResolver return this.constantPool.getConstLiteral(asLiteral(refsParam), true); } - private prepareListenerParameter(tagName: string, outputAst: t.BoundEvent): () => o.Expression[] { + private prepareListenerParameter(tagName: string, outputAst: t.BoundEvent, index: number): + () => o.Expression[] { let eventName: string = outputAst.name; if (outputAst.type === ParsedEventType.Animation) { eventName = prepareSyntheticAttributeName(`${outputAst.name}.${outputAst.phase}`); } const evNameSanitized = sanitizeIdentifier(eventName); const tagNameSanitized = sanitizeIdentifier(tagName); - const functionName = `${this.templateName}_${tagNameSanitized}_${evNameSanitized}_listener`; + const functionName = + `${this.templateName}_${tagNameSanitized}_${evNameSanitized}_${index}_listener`; return () => { diff --git a/packages/core/test/bundling/todo/bundle.golden_symbols.json b/packages/core/test/bundling/todo/bundle.golden_symbols.json index b9b56ee305..7cef770f1f 100644 --- a/packages/core/test/bundling/todo/bundle.golden_symbols.json +++ b/packages/core/test/bundling/todo/bundle.golden_symbols.json @@ -222,22 +222,22 @@ "name": "TemplateRef" }, { - "name": "ToDoAppComponent_footer_Template_6" + "name": "ToDoAppComponent_footer_6_Template" }, { - "name": "ToDoAppComponent_footer_button_Template_5" + "name": "ToDoAppComponent_footer_6_button_5_Template" }, { - "name": "ToDoAppComponent_section_Template_5" + "name": "ToDoAppComponent_section_5_Template" }, { - "name": "ToDoAppComponent_section_input_Template_1" + "name": "ToDoAppComponent_section_5_input_1_Template" }, { - "name": "ToDoAppComponent_section_li_Template_3" + "name": "ToDoAppComponent_section_5_li_3_Template" }, { - "name": "ToDoAppComponent_section_li_input_Template_6" + "name": "ToDoAppComponent_section_5_li_3_input_6_Template" }, { "name": "Todo"