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 5044fa56b9..96bd5fe292 100644 --- a/packages/compiler-cli/test/compliance/r3_compiler_compliance_spec.ts +++ b/packages/compiler-cli/test/compliance/r3_compiler_compliance_spec.ts @@ -788,7 +788,7 @@ describe('compiler compliance', () => { });`; const MyComponentDefinition = ` const $c1$ = ["foo", ""]; - const $c2$ = ["if", ""]; + const $c2$ = [${AttributeMarker.Template}, "if"]; function MyComponent_li_2_Template(rf, ctx) { if (rf & 1) { $r3$.ɵelementStart(0, "li"); @@ -1223,17 +1223,18 @@ describe('compiler compliance', () => { } }; const output = ` - const $_c0$ = [${AttributeMarker.Bindings}, "ngIf"]; - const $_c1$ = ["id", "second"]; + const $_c0$ = ["id", "second", ${AttributeMarker.Template}, "ngIf"]; + const $_c1$ = ["id", "third", ${AttributeMarker.Template}, "ngIf"]; + const $_c2$ = ["id", "second"]; function Cmp_div_0_Template(rf, ctx) { if (rf & 1) { - $r3$.ɵelementStart(0, "div", $_c1$); - $r3$.ɵprojection(1, 1); - $r3$.ɵelementEnd(); + $r3$.ɵelementStart(0, "div", $_c2$); + $r3$.ɵprojection(1, 1); + $r3$.ɵelementEnd(); } } - const $_c4$ = ["id", "third"]; + const $_c3$ = ["id", "third"]; function Cmp_div_1_Template(rf, ctx) { if (rf & 1) { - $r3$.ɵelementStart(0, "div", $_c4$); + $r3$.ɵelementStart(0, "div", $_c3$); $r3$.ɵtext(1, " No ng-content, no instructions generated. "); $r3$.ɵelementEnd(); } @@ -1244,14 +1245,14 @@ describe('compiler compliance', () => { $r3$.ɵprojection(1); } } - const $_c2$ = [[["span", "title", "tofirst"]]]; - const $_c3$ = ["span[title=toFirst]"]; + const $_c4$ = [[["span", "title", "tofirst"]]]; + const $_c5$ = ["span[title=toFirst]"]; … template: function Cmp_Template(rf, ctx) { if (rf & 1) { - $r3$.ɵprojectionDef($_c2$, $_c3$); + $r3$.ɵprojectionDef($_c4$, $_c5$); $r3$.ɵtemplate(0, Cmp_div_0_Template, 2, 0, "div", $_c0$); - $r3$.ɵtemplate(1, Cmp_div_1_Template, 2, 0, "div", $_c0$); + $r3$.ɵtemplate(1, Cmp_div_1_Template, 2, 0, "div", $_c1$); $r3$.ɵtemplate(2, Cmp_ng_template_2_Template, 2, 0, "ng-template"); } if (rf & 2) { @@ -2112,7 +2113,7 @@ describe('compiler compliance', () => { const MyComponentDefinition = ` const $c1$ = ["foo", ""]; - const $c2$ = ["if", ""]; + const $c2$ = [${AttributeMarker.Template}, "if"]; const $c3$ = ["baz", ""]; const $c4$ = ["bar", ""]; function MyComponent_div_3_span_2_Template(rf, ctx) { @@ -2203,9 +2204,9 @@ describe('compiler compliance', () => { }; const template = ` - const $c0$ = ["ngFor", "" , ${AttributeMarker.Bindings}, "ngForOf"]; + const $c0$ = [${AttributeMarker.Template}, "ngFor", "ngForOf"]; const $c1$ = ["foo", ""]; - const $c2$ = [${AttributeMarker.Bindings}, "ngIf"]; + const $c2$ = [${AttributeMarker.Template}, "ngIf"]; function MyComponent_div_0_span_3_Template(rf, ctx) { if (rf & 1) { @@ -2430,7 +2431,7 @@ describe('compiler compliance', () => { `; const MyComponentDefinition = ` - const $t1_attrs$ = ["for", "", ${AttributeMarker.Bindings}, "forOf"]; + const $t1_attrs$ = [${AttributeMarker.Template}, "for", "forOf"]; function MyComponent__svg_g_1_Template(rf, ctx) { if (rf & 1) { $r3$.ɵnamespaceSVG(); @@ -2509,7 +2510,7 @@ describe('compiler compliance', () => { `; const MyComponentDefinition = ` - const $t1_attrs$ = ["for", "", ${AttributeMarker.Bindings}, "forOf"]; + const $t1_attrs$ = [${AttributeMarker.Template}, "for", "forOf"]; function MyComponent_li_1_Template(rf, ctx) { if (rf & 1) { $r3$.ɵelementStart(0, "li"); @@ -2591,7 +2592,7 @@ describe('compiler compliance', () => { }; const MyComponentDefinition = ` - const $t4_attrs$ = ["for", "", ${AttributeMarker.Bindings}, "forOf"]; + const $t4_attrs$ = [${AttributeMarker.Template}, "for", "forOf"]; function MyComponent_li_1_li_4_Template(rf, ctx) { if (rf & 1) { $r3$.ɵelementStart(0, "li"); 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 567ea99b76..441b237027 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 @@ -236,7 +236,7 @@ describe('compiler compliance: directives', () => { const MyComponentDefinition = ` … - const $_c0$ = [${AttributeMarker.Bindings}, "ngIf"]; + const $_c0$ = ["directiveA", "", ${AttributeMarker.Template}, "ngIf"]; const $_c1$ = ["directiveA", ""]; function MyComponent_ng_container_0_Template(rf, ctx) { if (rf & 1) { @@ -339,7 +339,7 @@ describe('compiler compliance: directives', () => { // MyComponent definition should be: const MyComponentDefinition = ` … - const $c0_a0$ = ["someDirective", ""]; + const $c0_a0$ = [${AttributeMarker.Template}, "someDirective"]; … MyComponent.ngComponentDef = $r3$.ɵdefineComponent({ … 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 461e6b8f3d..2a13f675b1 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 @@ -417,7 +417,7 @@ describe('i18n support in the view compiler', () => { `; const output = String.raw ` - const $_c0$ = ["ngFor", "", ${AttributeMarker.Bindings}, "ngForOf"]; + const $_c0$ = [${AttributeMarker.Template}, "ngFor", "ngForOf"]; /** * @desc d * @meaning m @@ -548,7 +548,7 @@ describe('i18n support in the view compiler', () => { `; const output = String.raw ` - const $_c0$ = ["ngFor", "", ${AttributeMarker.Bindings}, "ngForOf"]; + const $_c0$ = [${AttributeMarker.Template}, "ngFor", "ngForOf"]; /** * @desc d * @meaning m @@ -1011,7 +1011,7 @@ describe('i18n support in the view compiler', () => { `; const output = String.raw ` - const $_c0$ = [${AttributeMarker.Bindings}, "ngIf"]; + const $_c0$ = [${AttributeMarker.Template}, "ngIf"]; const $MSG_EXTERNAL_7679414751795588050$$APP_SPEC_TS__1$ = goog.getMsg(" Some other content {$interpolation} {$startTagDiv} More nested levels with bindings {$interpolation_1} {$closeTagDiv}", { "interpolation": "\uFFFD0\uFFFD", "startTagDiv": "\uFFFD#3\uFFFD", @@ -1067,7 +1067,8 @@ describe('i18n support in the view compiler', () => { const output = String.raw ` const $_c0$ = ["src", "logo.png"]; - const $_c1$ = [${AttributeMarker.Bindings}, "ngIf"]; + const $_c1$ = ["src", "logo.png", ${AttributeMarker.Template}, "ngIf"]; + const $_c2$ = ["src", "logo.png", ${AttributeMarker.Bindings}, "title", ${AttributeMarker.Template}, "ngIf"]; function MyComponent_img_1_Template(rf, ctx) { if (rf & 1) { $r3$.ɵelement(0, "img", $_c0$); @@ -1076,11 +1077,11 @@ describe('i18n support in the view compiler', () => { const $MSG_EXTERNAL_2367729185105559721$ = goog.getMsg("App logo #{$interpolation}", { "interpolation": "\uFFFD0\uFFFD" }); - const $_c2$ = ["title", $MSG_EXTERNAL_2367729185105559721$]; + const $_c3$ = ["title", $MSG_EXTERNAL_2367729185105559721$]; function MyComponent_img_2_Template(rf, ctx) { if (rf & 1) { $r3$.ɵelementStart(0, "img", $_c0$); - $r3$.ɵi18nAttributes(1, $_c2$); + $r3$.ɵi18nAttributes(1, $_c3$); $r3$.ɵelementEnd(); } if (rf & 2) { @@ -1096,7 +1097,7 @@ describe('i18n support in the view compiler', () => { if (rf & 1) { $r3$.ɵelement(0, "img", $_c0$); $r3$.ɵtemplate(1, MyComponent_img_1_Template, 1, 0, "img", $_c1$); - $r3$.ɵtemplate(2, MyComponent_img_2_Template, 2, 1, "img", $_c1$); + $r3$.ɵtemplate(2, MyComponent_img_2_Template, 2, 1, "img", $_c2$); } if (rf & 2) { $r3$.ɵflushHooksUpTo(1); @@ -1136,7 +1137,7 @@ describe('i18n support in the view compiler', () => { `; const output = String.raw ` - const $_c0$ = [${AttributeMarker.Bindings}, "ngIf"]; + const $_c0$ = [${AttributeMarker.Template}, "ngIf"]; function MyComponent_div_2_div_4_Template(rf, ctx) { if (rf & 1) { $r3$.ɵi18nStart(0, $I18N_EXTERNAL_1221890473527419724$$APP_SPEC_TS_0$, 2); @@ -1232,7 +1233,7 @@ describe('i18n support in the view compiler', () => { `; const output = String.raw ` - const $_c0$ = [${AttributeMarker.Bindings}, "ngIf"]; + const $_c0$ = [${AttributeMarker.Template}, "ngIf"]; const $MSG_EXTERNAL_119975189388320493$$APP_SPEC_TS__1$ = goog.getMsg("Some other content {$startTagSpan}{$interpolation}{$closeTagSpan}", { "startTagSpan": "\uFFFD#2\uFFFD", "interpolation": "\uFFFD0\uFFFD", @@ -1864,15 +1865,16 @@ describe('i18n support in the view compiler', () => { const $I18N_EXTERNAL_7842238767399919809$$APP_SPEC_TS_0$ = $r3$.ɵi18nPostprocess($MSG_EXTERNAL_7842238767399919809$$APP_SPEC_TS_0$, { "VAR_SELECT": "\uFFFD0\uFFFD" }); - const $_c0$ = [${AttributeMarker.Bindings}, "ngIf"]; - const $_c1$ = ["title", "icu only"]; + const $_c0$ = ["title", "icu only", ${AttributeMarker.Template}, "ngIf"]; + const $_c1$ = ["title", "icu and text", ${AttributeMarker.Template}, "ngIf"]; + const $_c2$ = ["title", "icu only"]; const $MSG_EXTERNAL_8806993169187953163$$APP_SPEC_TS__3$ = goog.getMsg("{VAR_SELECT, select, 10 {ten} 20 {twenty} other {other}}"); const $I18N_EXTERNAL_8806993169187953163$$APP_SPEC_TS__3$ = $r3$.ɵi18nPostprocess($MSG_EXTERNAL_8806993169187953163$$APP_SPEC_TS__3$, { "VAR_SELECT": "\uFFFD0\uFFFD" }); function MyComponent_div_2_Template(rf, ctx) { if (rf & 1) { - $r3$.ɵelementStart(0, "div", $_c1$); + $r3$.ɵelementStart(0, "div", $_c2$); $r3$.ɵi18n(1, $I18N_EXTERNAL_8806993169187953163$$APP_SPEC_TS__3$); $r3$.ɵelementEnd(); } @@ -1883,7 +1885,7 @@ describe('i18n support in the view compiler', () => { $r3$.ɵi18nApply(1); } } - const $_c2$ = ["title", "icu and text"]; + const $_c3$ = ["title", "icu and text"]; const $MSG_EXTERNAL_1922743304863699161$$APP_SPEC_TS__5$ = goog.getMsg("{VAR_SELECT, select, 0 {no emails} 1 {one email} other {{$interpolation} emails}}", { "interpolation": "\uFFFD1\uFFFD" }); @@ -1892,7 +1894,7 @@ describe('i18n support in the view compiler', () => { }); function MyComponent_div_3_Template(rf, ctx) { if (rf & 1) { - $r3$.ɵelementStart(0, "div", $_c2$); + $r3$.ɵelementStart(0, "div", $_c3$); $r3$.ɵtext(1, " You have "); $r3$.ɵi18n(2, $I18N_EXTERNAL_1922743304863699161$$APP_SPEC_TS__5$); $r3$.ɵtext(3, ". "); @@ -1915,7 +1917,7 @@ describe('i18n support in the view compiler', () => { $r3$.ɵi18n(1, $I18N_EXTERNAL_7842238767399919809$$APP_SPEC_TS_0$); $r3$.ɵelementEnd(); $r3$.ɵtemplate(2, MyComponent_div_2_Template, 2, 1, "div", $_c0$); - $r3$.ɵtemplate(3, MyComponent_div_3_Template, 4, 2, "div", $_c0$); + $r3$.ɵtemplate(3, MyComponent_div_3_Template, 4, 2, "div", $_c1$); } if (rf & 2) { $r3$.ɵflushHooksUpTo(1); @@ -2113,7 +2115,7 @@ describe('i18n support in the view compiler', () => { const $I18N_APP_SPEC_TS_2$ = $r3$.ɵi18nPostprocess($MSG_APP_SPEC_TS_2$, { "VAR_SELECT": "\uFFFD1\uFFFD" }); - const $_c3$ = [${AttributeMarker.Bindings}, "ngIf"]; + const $_c3$ = [${AttributeMarker.Template}, "ngIf"]; const $MSG_APP_SPEC_TS__4$ = goog.getMsg("{VAR_SELECT, select, male {male} female {female} other {other}}"); const $I18N_APP_SPEC_TS__4$ = $r3$.ɵi18nPostprocess($MSG_APP_SPEC_TS__4$, { "VAR_SELECT": "\uFFFD0:1\uFFFD" @@ -2223,7 +2225,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" }); - const $_c0$ = [${AttributeMarker.Bindings}, "ngIf"]; + const $_c0$ = [${AttributeMarker.Template}, "ngIf"]; const $MSG_EXTERNAL_7068143081688428291$$APP_SPEC_TS__3$ = goog.getMsg("{VAR_SELECT, select, 10 {ten} 20 {twenty} 30 {thirty} other {other}}"); const $I18N_EXTERNAL_7068143081688428291$$APP_SPEC_TS__3$ = $r3$.ɵi18nPostprocess($MSG_EXTERNAL_7068143081688428291$$APP_SPEC_TS__3$, { "VAR_SELECT": "\uFFFD0:1\uFFFD" @@ -2287,7 +2289,7 @@ describe('i18n support in the view compiler', () => { const $I18N_EXTERNAL_7825031864601787094$$APP_SPEC_TS_1$ = $r3$.ɵi18nPostprocess($MSG_EXTERNAL_7825031864601787094$$APP_SPEC_TS_1$, { "VAR_SELECT": "\uFFFD0\uFFFD" }); - const $_c0$ = [${AttributeMarker.Bindings}, "ngIf"]; + const $_c0$ = [${AttributeMarker.Template}, "ngIf"]; const $MSG_EXTERNAL_2310343208266678305$$APP_SPEC_TS__3$ = goog.getMsg("{VAR_SELECT, select, 10 {ten} 20 {twenty} 30 {thirty} other {other: {$interpolation}}}", { "interpolation": "\uFFFD1:1\uFFFD" }); 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 6fb133db67..041339cb91 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 @@ -133,7 +133,7 @@ describe('compiler compliance: listen()', () => { }; const template = ` - const $t0_attrs$ = [${AttributeMarker.Bindings}, "ngIf"]; + const $t0_attrs$ = [${AttributeMarker.Template}, "ngIf"]; const $e_attrs$ = [${AttributeMarker.Bindings}, "click"]; function MyComponent_div_0_Template(rf, ctx) { 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 294b71f86b..33ca856a7b 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 @@ -50,13 +50,14 @@ 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.Bindings}, "ngForOf"]; - const $e0_attrs$ = [${AttributeMarker.Bindings}, "title", "click"]; + const $c0$ = [${AttributeMarker.Template}, "ngFor", "ngForOf"]; + const $c1$ = [${AttributeMarker.Bindings}, "title", "click", ${AttributeMarker.Template}, "ngFor", "ngForOf"]; + const $c2$ = [${AttributeMarker.Bindings}, "title", "click"]; 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$.ɵelementStart(0, "div", $c2$); $i0$.ɵlistener("click", function MyComponent_ul_0_li_1_div_1_Template_div_click_0_listener($event){ $i0$.ɵrestoreView($s$); const $inner$ = ctx.$implicit; @@ -83,7 +84,7 @@ describe('compiler compliance: template', () => { function MyComponent_ul_0_li_1_Template(rf, ctx) { if (rf & 1) { $i0$.ɵelementStart(0, "li"); - $i0$.ɵtemplate(1, MyComponent_ul_0_li_1_div_1_Template, 2, 2, "div", _c0); + $i0$.ɵtemplate(1, MyComponent_ul_0_li_1_div_1_Template, 2, 2, "div", $c1$); $i0$.ɵelementEnd(); } if (rf & 2) { @@ -96,7 +97,7 @@ describe('compiler compliance: template', () => { function MyComponent_ul_0_Template(rf, ctx) { if (rf & 1) { $i0$.ɵelementStart(0, "ul"); - $i0$.ɵtemplate(1, MyComponent_ul_0_li_1_Template, 2, 1, "li", _c0); + $i0$.ɵtemplate(1, MyComponent_ul_0_li_1_Template, 2, 1, "li", $c0$); $i0$.ɵelementEnd(); } if (rf & 2) { @@ -108,7 +109,7 @@ describe('compiler compliance: template', () => { // ... template:function MyComponent_Template(rf, ctx){ if (rf & 1) { - $i0$.ɵtemplate(0, MyComponent_ul_0_Template, 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)); @@ -144,7 +145,7 @@ describe('compiler compliance: template', () => { }; const template = ` - const $t0_attrs$ = ["ngFor", "", ${AttributeMarker.Bindings}, "ngForOf"]; + const $t0_attrs$ = [${AttributeMarker.Bindings}, "click", ${AttributeMarker.Template}, "ngFor", "ngForOf"]; const $e_attrs$ = [${AttributeMarker.Bindings}, "click"]; function MyComponent_div_0_Template(rf, ctx) { @@ -199,7 +200,7 @@ describe('compiler compliance: template', () => { }; const template = ` - const $c0$ = ["ngFor", "", ${AttributeMarker.Bindings}, "ngForOf"]; + const $c0$ = [${AttributeMarker.Template}, "ngFor", "ngForOf"]; function MyComponent_span_0_Template(rf, ctx) { if (rf & 1) { @@ -253,8 +254,8 @@ describe('compiler compliance: template', () => { }; const template = ` - const $c0$ = ["ngFor", "", ${AttributeMarker.Bindings}, "ngForOf"]; - const $c1$ = [${AttributeMarker.Bindings}, "ngIf"]; + const $c0$ = [${AttributeMarker.Template}, "ngFor", "ngForOf"]; + const $c1$ = [${AttributeMarker.Template}, "ngIf"]; function MyComponent_div_0_span_1_Template(rf, ctx) { if (rf & 1) { @@ -326,7 +327,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.Bindings}, "ngForOf"]; + const $c0$ = [${AttributeMarker.Template}, "ngFor", "ngForOf"]; function MyComponent_div_0_div_1_div_1_Template(rf, ctx) { if (rf & 1) { $i0$.ɵelementStart(0, "div"); @@ -344,7 +345,7 @@ describe('compiler compliance: template', () => { function MyComponent_div_0_div_1_Template(rf, ctx) { if (rf & 1) { $i0$.ɵelementStart(0, "div"); - $i0$.ɵtemplate(1, MyComponent_div_0_div_1_div_1_Template, 2, 2, "div", _c0); + $i0$.ɵtemplate(1, MyComponent_div_0_div_1_div_1_Template, 2, 2, "div", $c0$); $i0$.ɵelementEnd(); } if (rf & 2) { @@ -357,7 +358,7 @@ describe('compiler compliance: template', () => { function MyComponent_div_0_Template(rf, ctx) { if (rf & 1) { $i0$.ɵelementStart(0, "div"); - $i0$.ɵtemplate(1, MyComponent_div_0_div_1_Template, 2, 1, "div", _c0); + $i0$.ɵtemplate(1, MyComponent_div_0_div_1_Template, 2, 1, "div", $c0$); $i0$.ɵelementEnd(); } if (rf & 2) { @@ -369,7 +370,7 @@ describe('compiler compliance: template', () => { // ... template:function MyComponent_Template(rf, ctx){ if (rf & 1) { - $i0$.ɵtemplate(0, MyComponent_div_0_Template, 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)); @@ -645,7 +646,7 @@ describe('compiler compliance: template', () => { }; const template = ` - const $c0$ = [${AttributeMarker.Bindings}, "ngIf"]; + const $c0$ = [${AttributeMarker.Template}, "ngIf"]; function MyComponent_div_0_Template(rf, ctx) { if (rf & 1) { diff --git a/packages/compiler/src/render3/r3_ast.ts b/packages/compiler/src/render3/r3_ast.ts index 79fd5e4477..e51bd6ff89 100644 --- a/packages/compiler/src/render3/r3_ast.ts +++ b/packages/compiler/src/render3/r3_ast.ts @@ -81,10 +81,10 @@ export class Element implements Node { export class Template implements Node { constructor( public tagName: string, public attributes: TextAttribute[], public inputs: BoundAttribute[], - public outputs: BoundEvent[], public children: Node[], public references: Reference[], - public variables: Variable[], public sourceSpan: ParseSourceSpan, - public startSourceSpan: ParseSourceSpan|null, public endSourceSpan: ParseSourceSpan|null, - public i18n?: I18nAST) {} + public outputs: BoundEvent[], public templateAttrs: (BoundAttribute|TextAttribute)[], + public children: Node[], public references: Reference[], public variables: Variable[], + public sourceSpan: ParseSourceSpan, public startSourceSpan: ParseSourceSpan|null, + public endSourceSpan: ParseSourceSpan|null, public i18n?: I18nAST) {} visit(visitor: Visitor): Result { return visitor.visitTemplate(this); } } @@ -189,15 +189,18 @@ export class TransformVisitor implements Visitor { const newAttributes = transformAll(this, template.attributes); const newInputs = transformAll(this, template.inputs); const newOutputs = transformAll(this, template.outputs); + const newTemplateAttrs = transformAll(this, template.templateAttrs); const newChildren = transformAll(this, template.children); const newReferences = transformAll(this, template.references); const newVariables = transformAll(this, template.variables); if (newAttributes != template.attributes || newInputs != template.inputs || - newOutputs != template.outputs || newChildren != template.children || - newReferences != template.references || newVariables != template.variables) { + newOutputs != template.outputs || newTemplateAttrs != template.templateAttrs || + newChildren != template.children || newReferences != template.references || + newVariables != template.variables) { return new Template( - template.tagName, newAttributes, newInputs, newOutputs, newChildren, newReferences, - newVariables, template.sourceSpan, template.startSourceSpan, template.endSourceSpan); + template.tagName, newAttributes, newInputs, newOutputs, newTemplateAttrs, newChildren, + newReferences, newVariables, template.sourceSpan, template.startSourceSpan, + template.endSourceSpan); } return template; } diff --git a/packages/compiler/src/render3/r3_template_transform.ts b/packages/compiler/src/render3/r3_template_transform.ts index 371dda13b4..83521634e5 100644 --- a/packages/compiler/src/render3/r3_template_transform.ts +++ b/packages/compiler/src/render3/r3_template_transform.ts @@ -177,8 +177,9 @@ class HtmlAstToIvyAst implements html.Visitor { const attrs = this.extractAttributes(element.name, parsedProperties, i18nAttrsMeta); parsedElement = new t.Template( - element.name, attributes, attrs.bound, boundEvents, children, references, variables, - element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.i18n); + element.name, attributes, attrs.bound, boundEvents, [/* no template attributes */], + children, references, variables, element.sourceSpan, element.startSourceSpan, + element.endSourceSpan, element.i18n); } else { const attrs = this.extractAttributes(element.name, parsedProperties, i18nAttrsMeta); parsedElement = new t.Element( @@ -187,10 +188,25 @@ class HtmlAstToIvyAst implements html.Visitor { } if (elementHasInlineTemplate) { + // If this node is an inline-template (e.g. has *ngFor) then we need to create a template + // node that contains this node. + // Moreover, if the node is an element, then we need to hoist its attributes to the template + // node for matching against content projection selectors. const attrs = this.extractAttributes('ng-template', templateParsedProperties, i18nAttrsMeta); + const templateAttrs: (t.TextAttribute | t.BoundAttribute)[] = []; + attrs.literal.forEach(attr => templateAttrs.push(attr)); + attrs.bound.forEach(attr => templateAttrs.push(attr)); + const hoistedAttrs = parsedElement instanceof t.Element ? + { + attributes: parsedElement.attributes, + inputs: parsedElement.inputs, + outputs: parsedElement.outputs, + } : + {attributes: [], inputs: [], outputs: []}; // TODO(pk): test for this case parsedElement = new t.Template( - (parsedElement as t.Element).name, attrs.literal, attrs.bound, [], [parsedElement], [], + (parsedElement as t.Element).name, hoistedAttrs.attributes, hoistedAttrs.inputs, + hoistedAttrs.outputs, templateAttrs, [parsedElement], [/* no references */], templateVariables, element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.i18n); } diff --git a/packages/compiler/src/render3/view/template.ts b/packages/compiler/src/render3/view/template.ts index aa9dfbb989..5038bf8b44 100644 --- a/packages/compiler/src/render3/view/template.ts +++ b/packages/compiler/src/render3/view/template.ts @@ -576,9 +576,8 @@ export class TemplateDefinitionBuilder implements t.Visitor, LocalResolver attributes.push(...getAttributeNameLiterals(attr.name), o.literal(attr.value)); }); - // this will build the instructions so that they fall into the following syntax - // add attributes for directive matching purposes - attributes.push(...this.prepareBindingsAttrs(allOtherInputs, element.outputs, stylingBuilder)); + // add attributes for directive and projection matching purposes + attributes.push(...this.prepareNonRenderAttrs(allOtherInputs, element.outputs, stylingBuilder)); parameters.push(this.toAttrsParam(attributes)); // local refs (ex.:
) @@ -774,6 +773,7 @@ export class TemplateDefinitionBuilder implements t.Visitor, LocalResolver } visitTemplate(template: t.Template) { + const NG_TEMPLATE_TAG_NAME = 'ng-template'; const templateIndex = this.allocateDataSlot(); if (this.i18n) { @@ -794,13 +794,14 @@ export class TemplateDefinitionBuilder implements t.Visitor, LocalResolver ]; // find directives matching on a given node - this.matchDirectives('ng-template', template); + this.matchDirectives(NG_TEMPLATE_TAG_NAME, template); // prepare attributes parameter (including attributes used for directive matching) const attrsExprs: o.Expression[] = []; template.attributes.forEach( (a: t.TextAttribute) => { attrsExprs.push(asLiteral(a.name), asLiteral(a.value)); }); - attrsExprs.push(...this.prepareBindingsAttrs(template.inputs, template.outputs)); + attrsExprs.push(...this.prepareNonRenderAttrs( + template.inputs, template.outputs, undefined, template.templateAttrs)); parameters.push(this.toAttrsParam(attrsExprs)); // local refs (ex.: ) @@ -840,23 +841,19 @@ export class TemplateDefinitionBuilder implements t.Visitor, LocalResolver // handle property bindings e.g. ɵelementProperty(1, 'ngForOf', ɵbind(ctx.items)); const context = o.variable(CONTEXT_NAME); - template.inputs.forEach(input => { - const value = input.value.visit(this._valueConverter); - this.allocateBindingSlots(value); - this.updateInstruction(templateIndex, template.sourceSpan, R3.elementProperty, () => { - return [ - o.literal(templateIndex), o.literal(input.name), - this.convertPropertyBinding(context, value) - ]; - }); - }); + this.templatePropertyBindings(template, templateIndex, context, template.templateAttrs); - // Generate listeners for directive output - template.outputs.forEach((outputAst: t.BoundEvent) => { - this.creationInstruction( - outputAst.sourceSpan, R3.listener, - this.prepareListenerParameter('ng_template', outputAst, templateIndex)); - }); + // Only add normal input/output binding instructions on explicit ng-template elements. + if (template.tagName === NG_TEMPLATE_TAG_NAME) { + // Add the input bindings + this.templatePropertyBindings(template, templateIndex, context, template.inputs); + // Generate listeners for directive output + template.outputs.forEach((outputAst: t.BoundEvent) => { + this.creationInstruction( + outputAst.sourceSpan, R3.listener, + this.prepareListenerParameter('ng_template', outputAst, templateIndex)); + }); + } } // These should be handled in the template or element directly. @@ -949,6 +946,23 @@ export class TemplateDefinitionBuilder implements t.Visitor, LocalResolver private bindingContext() { return `${this._bindingContext++}`; } + private templatePropertyBindings( + template: t.Template, templateIndex: number, context: o.ReadVarExpr, + attrs: (t.BoundAttribute|t.TextAttribute)[]) { + attrs.forEach(input => { + if (input instanceof t.BoundAttribute) { + const value = input.value.visit(this._valueConverter); + this.allocateBindingSlots(value); + this.updateInstruction(templateIndex, template.sourceSpan, R3.elementProperty, () => { + return [ + o.literal(templateIndex), o.literal(input.name), + this.convertPropertyBinding(context, value) + ]; + }); + } + }); + } + // Bindings must only be resolved after all local refs have been visited, so all // instructions are queued in callbacks that execute once the initial pass has completed. // Otherwise, we wouldn't be able to support local refs that are defined after their @@ -1051,9 +1065,9 @@ export class TemplateDefinitionBuilder implements t.Visitor, LocalResolver * Note that this function will fully ignore all synthetic (@foo) attribute values * because those values are intended to always be generated as property instructions. */ - private prepareBindingsAttrs( - inputs: t.BoundAttribute[], outputs: t.BoundEvent[], - styles?: StylingBuilder): o.Expression[] { + private prepareNonRenderAttrs( + inputs: t.BoundAttribute[], outputs: t.BoundEvent[], styles?: StylingBuilder, + templateAttrs: (t.BoundAttribute|t.TextAttribute)[] = []): o.Expression[] { const alreadySeen = new Set(); const attrExprs: o.Expression[] = []; @@ -1102,6 +1116,11 @@ export class TemplateDefinitionBuilder implements t.Visitor, LocalResolver } } + if (templateAttrs.length) { + attrExprs.push(o.literal(core.AttributeMarker.Template)); + templateAttrs.forEach(attr => addAttrExpr(attr.name)); + } + return attrExprs; } diff --git a/packages/compiler/src/render3/view/util.ts b/packages/compiler/src/render3/view/util.ts index 3e51ebc1bc..876284e988 100644 --- a/packages/compiler/src/render3/view/util.ts +++ b/packages/compiler/src/render3/view/util.ts @@ -173,5 +173,9 @@ export function getAttrsForDirectiveMatching(elOrTpl: t.Element | t.Template): elOrTpl.inputs.forEach(i => { attributesMap[i.name] = ''; }); elOrTpl.outputs.forEach(o => { attributesMap[o.name] = ''; }); + if (elOrTpl instanceof t.Template) { + elOrTpl.templateAttrs.forEach(a => attributesMap[a.name] = ''); + } + return attributesMap; } diff --git a/packages/compiler/test/render3/r3_template_transform_spec.ts b/packages/compiler/test/render3/r3_template_transform_spec.ts index d41d598517..4b800f6153 100644 --- a/packages/compiler/test/render3/r3_template_transform_spec.ts +++ b/packages/compiler/test/render3/r3_template_transform_spec.ts @@ -32,6 +32,8 @@ class R3AstHumanizer implements t.Visitor { this.visitAll([ template.attributes, template.inputs, + template.outputs, + template.templateAttrs, template.references, template.variables, template.children, diff --git a/packages/core/src/render3/di.ts b/packages/core/src/render3/di.ts index b75f578d9a..639ebe8b20 100644 --- a/packages/core/src/render3/di.ts +++ b/packages/core/src/render3/di.ts @@ -17,10 +17,11 @@ import {getComponentDef, getDirectiveDef, getPipeDef} from './definition'; import {NG_ELEMENT_ID} from './fields'; import {DirectiveDef} from './interfaces/definition'; import {NO_PARENT_INJECTOR, NodeInjectorFactory, PARENT_INJECTOR, RelativeInjectorLocation, RelativeInjectorLocationFlags, TNODE, isFactory} from './interfaces/injector'; -import {TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeFlags, TNodeProviderIndexes, TNodeType, isNameOnlyAttributeMarker} from './interfaces/node'; +import {TContainerNode, TElementContainerNode, TElementNode, TNode, TNodeFlags, TNodeProviderIndexes, TNodeType} from './interfaces/node'; import {DECLARATION_VIEW, INJECTOR, LView, TData, TVIEW, TView, T_HOST} from './interfaces/view'; import {assertNodeOfPossibleTypes} from './node_assert'; import {getLView, getPreviousOrParentTNode, setTNodeAndViewData} from './state'; +import {isNameOnlyAttributeMarker} from './util/attrs_utils'; import {getParentInjectorIndex, getParentInjectorView, hasParentInjector} from './util/injector_utils'; import {renderStringify} from './util/misc_utils'; import {findComponentView} from './util/view_traversal_utils'; diff --git a/packages/core/src/render3/interfaces/node.ts b/packages/core/src/render3/interfaces/node.ts index 79bf033e9e..7eadf2c58c 100644 --- a/packages/core/src/render3/interfaces/node.ts +++ b/packages/core/src/render3/interfaces/node.ts @@ -149,10 +149,6 @@ export const enum AttributeMarker { Template = 4, } -export function isNameOnlyAttributeMarker(marker: string | AttributeMarker) { - return marker === AttributeMarker.Bindings || marker === AttributeMarker.Template; -} - /** * A combination of: * - attribute names and values diff --git a/packages/core/src/render3/node_selector_matcher.ts b/packages/core/src/render3/node_selector_matcher.ts index b5c63a4980..d4af2755cf 100644 --- a/packages/core/src/render3/node_selector_matcher.ts +++ b/packages/core/src/render3/node_selector_matcher.ts @@ -10,9 +10,10 @@ import '../util/ng_dev_mode'; import {assertDefined, assertNotEqual} from '../util/assert'; -import {AttributeMarker, TAttributes, TNode, TNodeType, isNameOnlyAttributeMarker, unusedValueExportToPlacateAjd as unused1} from './interfaces/node'; +import {AttributeMarker, TAttributes, TNode, TNodeType, unusedValueExportToPlacateAjd as unused1} from './interfaces/node'; import {CssSelector, CssSelectorList, NG_PROJECT_AS_ATTR_NAME, SelectorFlags, unusedValueExportToPlacateAjd as unused2} from './interfaces/projection'; import {getInitialClassNameValue} from './styling/class_and_style_bindings'; +import {isNameOnlyAttributeMarker} from './util/attrs_utils'; const unusedValueToPlacateAjd = unused1 + unused2; @@ -35,7 +36,7 @@ function isCssClassMatching(nodeClassAttrVal: string, cssClassToMatch: string): /** * Function that checks whether a given tNode matches tag-based selector and has a valid type. * - * Matching can be perfomed in 2 modes: projection mode (when we project nodes) and regular + * Matching can be performed in 2 modes: projection mode (when we project nodes) and regular * directive matching mode. In "projection" mode, we do not need to check types, so if tag name * matches selector, we declare a match. In "directive matching" mode, we also check whether tNode * is of expected type: @@ -53,8 +54,10 @@ function hasTagAndTypeMatch( /** * A utility function to match an Ivy node static data against a simple CSS selector * - * @param node static data to match - * @param selector + * @param node static data of the node to match + * @param selector The selector to try matching against the node. + * @param isProjectionMode if `true` we are matching for content projection, otherwise we are doing + * directive matching. * @returns true if node matches the selector. */ export function isNodeMatchingSelector( @@ -64,14 +67,7 @@ export function isNodeMatchingSelector( const nodeAttrs = tNode.attrs || []; // Find the index of first attribute that has no value, only a name. - let nameOnlyMarkerIdx = nodeAttrs && nodeAttrs.length; - for (let i = 0; i < nodeAttrs.length; i++) { - const nodeAttr = nodeAttrs[i]; - if (isNameOnlyAttributeMarker(nodeAttr)) { - nameOnlyMarkerIdx = i; - break; - } - } + const nameOnlyMarkerIdx = getNameOnlyMarkerIndex(nodeAttrs); // When processing ":not" selectors, we skip to the next ":not" if the // current one doesn't match @@ -114,8 +110,11 @@ export function isNodeMatchingSelector( continue; } + const isInlineTemplate = + tNode.type == TNodeType.Container && tNode.tagName !== NG_TEMPLATE_SELECTOR; const attrName = (mode & SelectorFlags.CLASS) ? 'class' : current; - const attrIndexInNode = findAttrIndexInNode(attrName, nodeAttrs); + const attrIndexInNode = + findAttrIndexInNode(attrName, nodeAttrs, isInlineTemplate, isProjectionMode); if (attrIndexInNode === -1) { if (isPositive(mode)) return false; @@ -125,12 +124,11 @@ export function isNodeMatchingSelector( if (selectorAttrValue !== '') { let nodeAttrValue: string; - const maybeAttrName = nodeAttrs[attrIndexInNode]; if (attrIndexInNode > nameOnlyMarkerIdx) { nodeAttrValue = ''; } else { ngDevMode && assertNotEqual( - maybeAttrName, AttributeMarker.NamespaceURI, + nodeAttrs[attrIndexInNode], AttributeMarker.NamespaceURI, 'We do not match directives on namespaced attributes'); nodeAttrValue = nodeAttrs[attrIndexInNode + 1] as string; } @@ -164,34 +162,64 @@ function readClassValueFromTNode(tNode: TNode): string { } /** - * Examines an attribute's definition array from a node to find the index of the - * attribute with the specified name. + * Examines the attribute's definition array for a node to find the index of the + * attribute that matches the given `name`. * - * NOTE: Will not find namespaced attributes. + * NOTE: This will not match namespaced attributes. + * + * Attribute matching depends upon `isInlineTemplate` and `isProjectionMode`. + * The following table summarizes which types of attributes we attempt to match: + * + * ========================================================================================= + * Modes | Normal Attributes | Bindings Attributes | Template Attributes + * ========================================================================================= + * Inline + Projection | YES | YES | NO + * ----------------------------------------------------------------------------------------- + * Inline + Directive | NO | NO | YES + * ----------------------------------------------------------------------------------------- + * Non-inline + Projection | YES | YES | NO + * ----------------------------------------------------------------------------------------- + * Non-inline + Directive | YES | YES | NO + * ========================================================================================= * * @param name the name of the attribute to find * @param attrs the attribute array to examine + * @param isInlineTemplate true if the node being matched is an inline template (e.g. `*ngFor`) + * rather than a manually expanded template node (e.g ``). + * @param isProjectionMode true if we are matching against content projection otherwise we are + * matching against directives. */ -function findAttrIndexInNode(name: string, attrs: TAttributes | null): number { +function findAttrIndexInNode( + name: string, attrs: TAttributes | null, isInlineTemplate: boolean, + isProjectionMode: boolean): number { if (attrs === null) return -1; - let nameOnlyMode = false; - let i = 0; - while (i < attrs.length) { - const maybeAttrName = attrs[i]; - if (maybeAttrName === name) { - return i; - } else if (maybeAttrName === AttributeMarker.NamespaceURI) { - // NOTE(benlesh): will not find namespaced attributes. This is by design. - i += 4; - } else { - if (isNameOnlyAttributeMarker(maybeAttrName)) { - nameOnlyMode = true; - } - i += nameOnlyMode ? 1 : 2; - } - } - return -1; + let i = 0; + + if (isProjectionMode || !isInlineTemplate) { + let bindingsMode = false; + while (i < attrs.length) { + const maybeAttrName = attrs[i]; + if (maybeAttrName === name) { + return i; + } else if (maybeAttrName === AttributeMarker.Bindings) { + bindingsMode = true; + } else if (maybeAttrName === AttributeMarker.Template) { + // We do not care about Template attributes in this scenario. + break; + } else if (maybeAttrName === AttributeMarker.NamespaceURI) { + // Skip the whole namespaced attribute and value. This is by design. + i += 4; + continue; + } + // In binding mode there are only names, rather than name-value pairs. + i += bindingsMode ? 1 : 2; + } + // We did not match the attribute + return -1; + } else { + return matchTemplateAttribute(attrs, name); + } } export function isNodeMatchingSelectorList( @@ -222,8 +250,8 @@ export function getProjectAsAttrValue(tNode: TNode): string|null { * Checks a given node against matching projection selectors and returns * selector index (or 0 if none matched). * - * This function takes into account the ngProjectAs attribute: if present its value will be compared - * to the raw (un-parsed) CSS selector instead of using standard selector matching logic. + * This function takes into account the ngProjectAs attribute: if present its value will be + * compared to the raw (un-parsed) CSS selector instead of using standard selector matching logic. */ export function matchingProjectionSelectorIndex( tNode: TNode, selectors: CssSelectorList[], textSelectors: string[]): number { @@ -239,3 +267,25 @@ export function matchingProjectionSelectorIndex( } return 0; } + +function getNameOnlyMarkerIndex(nodeAttrs: TAttributes) { + for (let i = 0; i < nodeAttrs.length; i++) { + const nodeAttr = nodeAttrs[i]; + if (isNameOnlyAttributeMarker(nodeAttr)) { + return i; + } + } + return nodeAttrs.length; +} + +function matchTemplateAttribute(attrs: TAttributes, name: string): number { + let i = attrs.indexOf(AttributeMarker.Template); + if (i > -1) { + i++; + while (i < attrs.length) { + if (attrs[i] === name) return i; + i++; + } + } + return -1; +} diff --git a/packages/core/src/render3/util/attrs_utils.ts b/packages/core/src/render3/util/attrs_utils.ts index f810cd6b0d..ec580a25f5 100644 --- a/packages/core/src/render3/util/attrs_utils.ts +++ b/packages/core/src/render3/util/attrs_utils.ts @@ -105,3 +105,14 @@ export function attrsStylingIndexOf(attrs: TAttributes, startIndex: number): num } return -1; } + +/** + * Test whether the given value is a marker that indicates that the following + * attribute values in a `TAttributes` array are only the names of attributes, + * and not name-value pairs. + * @param marker The attribute marker to test. + * @returns true if the marker is a "name-only" marker (e.g. `Bindings` or `Template`). + */ +export function isNameOnlyAttributeMarker(marker: string | AttributeMarker) { + return marker === AttributeMarker.Bindings || marker === AttributeMarker.Template; +} diff --git a/packages/core/test/render3/common_integration_spec.ts b/packages/core/test/render3/common_integration_spec.ts index d50d4b8acd..de1fd83e05 100644 --- a/packages/core/test/render3/common_integration_spec.ts +++ b/packages/core/test/render3/common_integration_spec.ts @@ -48,7 +48,9 @@ describe('@angular/common integration', () => { template: (rf: RenderFlags, ctx: MyApp) => { if (rf & RenderFlags.Create) { elementStart(0, 'ul'); - { template(1, liTemplate, 2, 1, 'li', ['ngForOf', '']); } + { + template(1, liTemplate, 2, 1, 'li', [AttributeMarker.Template, 'ngFor', 'ngForOf']); + } elementEnd(); } if (rf & RenderFlags.Update) { @@ -111,7 +113,9 @@ describe('@angular/common integration', () => { template: (rf: RenderFlags, ctx: MyApp) => { if (rf & RenderFlags.Create) { elementStart(0, 'ul'); - { template(1, liTemplate, 2, 3, 'li', ['ngForOf', '']); } + { + template(1, liTemplate, 2, 3, 'li', [AttributeMarker.Template, 'ngFor', 'ngForOf']); + } elementEnd(); } if (rf & RenderFlags.Update) { @@ -175,7 +179,8 @@ describe('@angular/common integration', () => { vars: 1, template: (rf: RenderFlags, ctx: MyApp) => { if (rf & RenderFlags.Create) { - template(0, ngForTemplate, 1, 0, 'comp', ['ngForOf', '']); + template( + 0, ngForTemplate, 1, 0, 'comp', [AttributeMarker.Template, 'ngFor', 'ngForOf']); } if (rf & RenderFlags.Update) { elementProperty(0, 'ngForOf', bind(ctx.rows)); @@ -247,7 +252,9 @@ describe('@angular/common integration', () => { } elementEnd(); elementStart(2, 'ul'); - { template(3, liTemplate, 2, 1, 'li', ['ngForOf', '']); } + { + template(3, liTemplate, 2, 1, 'li', [AttributeMarker.Template, 'ngFor', 'ngForOf']); + } elementEnd(); } if (rf & RenderFlags.Update) { @@ -302,7 +309,9 @@ describe('@angular/common integration', () => { template: (rf: RenderFlags, ctx: MyApp) => { if (rf & RenderFlags.Create) { elementStart(0, 'ul'); - { template(1, liTemplate, 2, 1, 'li', ['ngForOf', '']); } + { + template(1, liTemplate, 2, 1, 'li', [AttributeMarker.Template, 'ngFor', 'ngForOf']); + } elementEnd(); } if (rf & RenderFlags.Update) { @@ -317,7 +326,9 @@ describe('@angular/common integration', () => { function liTemplate(rf: RenderFlags, ctx: any) { if (rf & RenderFlags.Create) { elementStart(0, 'li'); - { template(1, spanTemplate, 2, 3, 'span', ['ngForOf', '']); } + { + template(1, spanTemplate, 2, 3, 'span', [AttributeMarker.Template, 'ngFor', 'ngForOf']); + } elementEnd(); } if (rf & RenderFlags.Update) { @@ -392,7 +403,7 @@ describe('@angular/common integration', () => { vars: 1, template: (rf: RenderFlags, ctx: MyApp) => { if (rf & RenderFlags.Create) { - template(0, divTemplate, 2, 1, 'div', ['ngForOf', '']); + template(0, divTemplate, 2, 1, 'div', [AttributeMarker.Template, 'ngFor', 'ngForOf']); } if (rf & RenderFlags.Update) { elementProperty(0, 'ngForOf', bind(ctx.items)); @@ -406,7 +417,7 @@ describe('@angular/common integration', () => { function divTemplate(rf: RenderFlags, ctx: any) { if (rf & RenderFlags.Create) { elementStart(0, 'div'); - { template(1, pTemplate, 3, 2, 'p', ['ngForOf', '']); } + { template(1, pTemplate, 3, 2, 'p', [AttributeMarker.Template, 'ngFor', 'ngForOf']); } elementEnd(); } if (rf & RenderFlags.Update) { @@ -486,7 +497,7 @@ describe('@angular/common integration', () => { vars: 1, template: (rf: RenderFlags, ctx: MyApp) => { if (rf & RenderFlags.Create) { - template(0, divTemplate, 2, 1, 'div', ['ngForOf', '']); + template(0, divTemplate, 2, 1, 'div', [AttributeMarker.Template, 'ngFor', 'ngForOf']); } if (rf & RenderFlags.Update) { elementProperty(0, 'ngForOf', bind(ctx.items)); @@ -500,7 +511,10 @@ describe('@angular/common integration', () => { function divTemplate(rf: RenderFlags, ctx: any) { if (rf & RenderFlags.Create) { elementStart(0, 'div'); - { template(1, innerDivTemplate, 2, 1, 'div', ['ngForOf', '']); } + { + template( + 1, innerDivTemplate, 2, 1, 'div', [AttributeMarker.Template, 'ngFor', 'ngForOf']); + } elementEnd(); } if (rf & RenderFlags.Update) { @@ -512,7 +526,9 @@ describe('@angular/common integration', () => { function innerDivTemplate(rf: RenderFlags, ctx: any) { if (rf & RenderFlags.Create) { elementStart(0, 'div'); - { template(1, spanTemplate, 2, 2, 'span', ['ngForOf', '']); } + { + template(1, spanTemplate, 2, 2, 'span', [AttributeMarker.Template, 'ngFor', 'ngForOf']); + } elementEnd(); } if (rf & RenderFlags.Update) { @@ -654,7 +670,8 @@ describe('@angular/common integration', () => { vars: 1, template: (rf: RenderFlags, ctx: MyApp) => { if (rf & RenderFlags.Create) { - template(0, itemTemplate0, 2, 1, 'span', ['ngForOf', '']); + template( + 0, itemTemplate0, 2, 1, 'span', [AttributeMarker.Template, 'ngFor', 'ngForOf']); } if (rf & RenderFlags.Update) { elementProperty(0, 'ngForOf', bind(ctx.items)); @@ -668,7 +685,10 @@ describe('@angular/common integration', () => { function itemTemplate0(rf: RenderFlags, ctx: any) { if (rf & RenderFlags.Create) { elementStart(0, 'span'); - { template(1, itemTemplate1, 2, 1, 'span', ['ngForOf', '']); } + { + template( + 1, itemTemplate1, 2, 1, 'span', [AttributeMarker.Template, 'ngFor', 'ngForOf']); + } elementEnd(); } if (rf & RenderFlags.Update) { @@ -680,7 +700,10 @@ describe('@angular/common integration', () => { function itemTemplate1(rf: RenderFlags, ctx: any) { if (rf & RenderFlags.Create) { elementStart(0, 'span'); - { template(1, itemTemplate2, 2, 1, 'span', ['ngForOf', '']); } + { + template( + 1, itemTemplate2, 2, 1, 'span', [AttributeMarker.Template, 'ngFor', 'ngForOf']); + } elementEnd(); } if (rf & RenderFlags.Update) { @@ -692,7 +715,10 @@ describe('@angular/common integration', () => { function itemTemplate2(rf: RenderFlags, ctx: any) { if (rf & RenderFlags.Create) { elementStart(0, 'span'); - { template(1, itemTemplate3, 2, 1, 'span', ['ngForOf', '']); } + { + template( + 1, itemTemplate3, 2, 1, 'span', [AttributeMarker.Template, 'ngFor', 'ngForOf']); + } elementEnd(); } if (rf & RenderFlags.Update) { @@ -704,7 +730,10 @@ describe('@angular/common integration', () => { function itemTemplate3(rf: RenderFlags, ctx: any) { if (rf & RenderFlags.Create) { elementStart(0, 'span'); - { template(1, itemTemplate4, 2, 1, 'span', ['ngForOf', '']); } + { + template( + 1, itemTemplate4, 2, 1, 'span', [AttributeMarker.Template, 'ngFor', 'ngForOf']); + } elementEnd(); } if (rf & RenderFlags.Update) { @@ -716,7 +745,10 @@ describe('@angular/common integration', () => { function itemTemplate4(rf: RenderFlags, ctx: any) { if (rf & RenderFlags.Create) { elementStart(0, 'span'); - { template(1, itemTemplate5, 2, 1, 'span', ['ngForOf', '']); } + { + template( + 1, itemTemplate5, 2, 1, 'span', [AttributeMarker.Template, 'ngFor', 'ngForOf']); + } elementEnd(); } if (rf & RenderFlags.Update) { @@ -728,7 +760,10 @@ describe('@angular/common integration', () => { function itemTemplate5(rf: RenderFlags, ctx: any) { if (rf & RenderFlags.Create) { elementStart(0, 'span'); - { template(1, itemTemplate6, 2, 1, 'span', ['ngForOf', '']); } + { + template( + 1, itemTemplate6, 2, 1, 'span', [AttributeMarker.Template, 'ngFor', 'ngForOf']); + } elementEnd(); } if (rf & RenderFlags.Update) { @@ -740,7 +775,10 @@ describe('@angular/common integration', () => { function itemTemplate6(rf: RenderFlags, ctx: any) { if (rf & RenderFlags.Create) { elementStart(0, 'span'); - { template(1, itemTemplate7, 2, 1, 'span', ['ngForOf', '']); } + { + template( + 1, itemTemplate7, 2, 1, 'span', [AttributeMarker.Template, 'ngFor', 'ngForOf']); + } elementEnd(); } if (rf & RenderFlags.Update) { @@ -752,7 +790,10 @@ describe('@angular/common integration', () => { function itemTemplate7(rf: RenderFlags, ctx: any) { if (rf & RenderFlags.Create) { elementStart(0, 'span'); - { template(1, itemTemplate8, 2, 10, 'span', ['ngForOf', '']); } + { + template( + 1, itemTemplate8, 2, 10, 'span', [AttributeMarker.Template, 'ngFor', 'ngForOf']); + } elementEnd(); } if (rf & RenderFlags.Update) { @@ -822,8 +863,8 @@ describe('@angular/common integration', () => { */ template: (rf: RenderFlags, ctx: MyApp) => { if (rf & RenderFlags.Create) { - template(0, templateOne, 2, 1, 'div', ['ngIf', '']); - template(1, templateTwo, 2, 1, 'div', ['ngIf', '']); + template(0, templateOne, 2, 1, 'div', [AttributeMarker.Template, 'ngIf']); + template(1, templateTwo, 2, 1, 'div', [AttributeMarker.Template, 'ngIf']); } if (rf & RenderFlags.Update) { elementProperty(0, 'ngIf', bind(ctx.showing)); @@ -892,7 +933,7 @@ describe('@angular/common integration', () => { vars: 1, template: (rf: RenderFlags, ctx: AppComponent) => { if (rf & RenderFlags.Create) { - template(0, divTemplate, 2, 1, 'div', ['ngIf', '']); + template(0, divTemplate, 2, 1, 'div', [AttributeMarker.Template, 'ngIf']); } if (rf & RenderFlags.Update) { elementProperty(0, 'ngIf', bind(ctx.showing)); @@ -906,7 +947,7 @@ describe('@angular/common integration', () => { function divTemplate(rf: RenderFlags, ctx: any) { if (rf & RenderFlags.Create) { elementStart(0, 'div'); - { template(1, outerDivTemplate, 2, 1, 'div', ['ngIf', '']); } + { template(1, outerDivTemplate, 2, 1, 'div', [AttributeMarker.Template, 'ngIf']); } elementEnd(); } if (rf & RenderFlags.Update) { @@ -918,7 +959,7 @@ describe('@angular/common integration', () => { function outerDivTemplate(rf: RenderFlags, ctx: any) { if (rf & RenderFlags.Create) { elementStart(0, 'div'); - { template(1, innerDivTemplate, 2, 1, 'div', ['ngIf', '']); } + { template(1, innerDivTemplate, 2, 1, 'div', [AttributeMarker.Template, 'ngIf']); } elementEnd(); } if (rf & RenderFlags.Update) { diff --git a/packages/core/test/render3/component_spec.ts b/packages/core/test/render3/component_spec.ts index 6a4064d6fc..ec3e944626 100644 --- a/packages/core/test/render3/component_spec.ts +++ b/packages/core/test/render3/component_spec.ts @@ -186,7 +186,7 @@ it('should not invoke renderer destroy method for embedded views', () => { elementStart(0, 'div'); text(1, 'Root view'); elementEnd(); - template(2, MyComponent_div_Template_2, 2, 0, null, [AttributeMarker.Bindings, 'ngIf']); + template(2, MyComponent_div_Template_2, 2, 0, 'div', [AttributeMarker.Template, 'ngIf']); } if (rf & RenderFlags.Update) { elementProperty(2, 'ngIf', bind(ctx.visible)); @@ -514,8 +514,12 @@ describe('recursive components', () => { if (rf & RenderFlags.Create) { text(0); - template(1, IfTemplate, 1, 1, 'ng-if-tree', [AttributeMarker.Bindings, 'ngIf']); - template(2, IfTemplate2, 1, 1, 'ng-if-tree', [AttributeMarker.Bindings, 'ngIf']); + template( + 1, IfTemplate, 1, 1, 'ng-if-tree', + [AttributeMarker.Bindings, 'data', AttributeMarker.Template, 'ngIf']); + template( + 2, IfTemplate2, 1, 1, 'ng-if-tree', + [AttributeMarker.Bindings, 'data', AttributeMarker.Template, 'ngIf']); } if (rf & RenderFlags.Update) { textBinding(0, bind(ctx.data.value)); diff --git a/packages/core/test/render3/content_spec.ts b/packages/core/test/render3/content_spec.ts index c2cfe38ae2..caf51bbc71 100644 --- a/packages/core/test/render3/content_spec.ts +++ b/packages/core/test/render3/content_spec.ts @@ -945,7 +945,7 @@ describe('content projection', () => { projectionDef([[['div']]], ['div']); projection(0); text(1, 'Before-'); - template(2, IfTemplate, 1, 0, '', [AttributeMarker.Bindings, 'ngIf']); + template(2, IfTemplate, 1, 0, 'ng-template', [AttributeMarker.Bindings, 'ngIf']); text(3, '-After'); } if (rf & RenderFlags.Update) { @@ -1184,7 +1184,7 @@ describe('content projection', () => { const Child = createComponent('child', function(rf: RenderFlags, ctx: any) { if (rf & RenderFlags.Create) { projectionDef(); - { template(0, ForTemplate, 3, 1, undefined, ['ngForOf', '']); } + { template(0, ForTemplate, 3, 1, 'div', [AttributeMarker.Template, 'ngFor', 'ngForOf']); } } if (rf & RenderFlags.Update) { elementProperty(0, 'ngForOf', bind(items)); @@ -1461,7 +1461,7 @@ describe('content projection', () => { // // - // + // // // function MyApp_ng_container_1_child_comp_1_Template(rf: RenderFlags, ctx: any) { @@ -1472,7 +1472,9 @@ describe('content projection', () => { function MyApp_ng_container_1_Template(rf: RenderFlags, ctx: any) { if (rf & RenderFlags.Create) { elementContainerStart(0); - template(1, MyApp_ng_container_1_child_comp_1_Template, 1, 0, 'nested-comp', [3, 'ngIf']); + template( + 1, MyApp_ng_container_1_child_comp_1_Template, 1, 0, 'nested-comp', + [AttributeMarker.Template, 'ngIf']); elementContainerEnd(); } if (rf & RenderFlags.Update) { @@ -1495,7 +1497,7 @@ describe('content projection', () => { elementStart(0, 'root-comp'); template( 1, MyApp_ng_container_1_Template, 2, 1, 'ng-container', - ['ngFor', '', 3, 'ngForOf']); + [AttributeMarker.Template, 'ngFor', 'ngForOf']); elementEnd(); } if (rf & RenderFlags.Update) { @@ -2089,7 +2091,7 @@ describe('content projection', () => { const Parent = createComponent('parent', function(rf: RenderFlags, ctx: {value: any}) { if (rf & RenderFlags.Create) { elementStart(0, 'child'); - { template(1, IfTemplate, 2, 0, 'div', [AttributeMarker.Bindings, 'ngIf']); } + { template(1, IfTemplate, 2, 0, 'div', [AttributeMarker.Template, 'ngIf']); } elementEnd(); } if (rf & RenderFlags.Update) { diff --git a/packages/core/test/render3/di_spec.ts b/packages/core/test/render3/di_spec.ts index bbd6952bea..f972dabf03 100644 --- a/packages/core/test/render3/di_spec.ts +++ b/packages/core/test/render3/di_spec.ts @@ -490,7 +490,7 @@ describe('di', () => { const App = createComponent('app', (rf: RenderFlags, ctx: any) => { if (rf & RenderFlags.Create) { elementStart(0, 'div', ['dirB', '']); - { template(1, IfTemplate, 4, 1, 'div', [AttributeMarker.Bindings, 'ngIf', '']); } + { template(1, IfTemplate, 4, 1, 'div', [AttributeMarker.Template, 'ngIf']); } elementEnd(); } if (rf & RenderFlags.Update) { @@ -1245,7 +1245,10 @@ describe('di', () => { const App = createComponent('app', function(rf: RenderFlags, ctx: any) { if (rf & RenderFlags.Create) { elementStart(0, 'div', ['dirB', '']); - { template(1, IfTemplate, 1, 0, 'div', ['ngIf', '']); } + { + template( + 1, IfTemplate, 1, 0, 'div', ['dirA', '', AttributeMarker.Template, 'ngIf']); + } elementEnd(); } if (rf & RenderFlags.Update) { @@ -1787,7 +1790,7 @@ describe('di', () => { it('should inject current component ChangeDetectorRef into directives on the same node as components', () => { - /** {{ dir.value }} */ + /** {{ dir.value }} */ const MyApp = createComponent('my-app', function(rf: RenderFlags, ctx: any) { if (rf & RenderFlags.Create) { element(0, 'my-comp', ['dir', '', 'dirSame', ''], ['dir', 'dir']); @@ -1821,7 +1824,7 @@ describe('di', () => { consts: 3, vars: 1, factory: () => new MyApp(directiveInject(ChangeDetectorRef as any)), - /**
{{ dir.value }}
*/ + /**
{{ dir.value }}
*/ template: function(rf: RenderFlags, ctx: any) { if (rf & RenderFlags.Create) { elementStart(0, 'div', ['dir', '', 'dirSame', ''], ['dir', 'dir']); @@ -1859,7 +1862,7 @@ describe('di', () => { factory: () => new MyApp(directiveInject(ChangeDetectorRef as any)), /** * - *
+ *
*
* {{ dir.value }} */ @@ -1903,7 +1906,7 @@ describe('di', () => { vars: 0, /** * % if (showing) { - *
{{ dir.value }}
+ *
{{ dir.value }}
* % } */ template: function(rf: RenderFlags, ctx: MyApp) { @@ -1967,10 +1970,15 @@ describe('di', () => { factory: () => new MyApp(directiveInject(ChangeDetectorRef as any)), consts: 1, vars: 0, - /**
{{ dir.value }}
*/ + /**
{{ dir.value }}
*/ template: function(rf: RenderFlags, ctx: MyApp) { if (rf & RenderFlags.Create) { - template(0, C1, 3, 1, 'div', ['ngIf', 'showing']); + template( + 0, C1, 3, 1, 'div', + ['dir', '', 'dirSame', '', AttributeMarker.Template, 'ngIf']); + } + if (rf & RenderFlags.Update) { + elementProperty(0, 'ngIf', bind(ctx.showing)); } }, directives: directives diff --git a/packages/core/test/render3/directive_spec.ts b/packages/core/test/render3/directive_spec.ts index 045bbcf373..ab65c7828f 100644 --- a/packages/core/test/render3/directive_spec.ts +++ b/packages/core/test/render3/directive_spec.ts @@ -208,7 +208,7 @@ describe('directive', () => { if (rf & RenderFlags.Create) { template( 0, MyComponent_ng_container_Template_0, 2, 0, 'ng-container', - [AttributeMarker.Bindings, 'ngIf']); + ['directiveA', '', AttributeMarker.Template, 'ngIf']); } if (rf & RenderFlags.Update) { elementProperty(0, 'ngIf', bind(ctx.visible)); diff --git a/packages/core/test/render3/discovery_utils_spec.ts b/packages/core/test/render3/discovery_utils_spec.ts index 1a9a2a8637..52b16866d5 100644 --- a/packages/core/test/render3/discovery_utils_spec.ts +++ b/packages/core/test/render3/discovery_utils_spec.ts @@ -7,7 +7,7 @@ */ import {StaticInjector} from '../../src/di/injector'; import {createInjector} from '../../src/di/r3_injector'; -import {ProvidersFeature, RenderFlags, defineComponent, defineDirective, elementContainerEnd, elementContainerStart, getHostElement, i18n, i18nApply, i18nExp} from '../../src/render3/index'; +import {AttributeMarker, ProvidersFeature, RenderFlags, defineComponent, defineDirective, elementContainerEnd, elementContainerStart, getHostElement, i18n, i18nApply, i18nExp} from '../../src/render3/index'; import {getComponent, getContext, getDirectives, getInjectionTokens, getInjector, getListeners, getLocalRefs, getRootComponents, getViewComponent, loadLContext} from '../../src/render3/util/discovery_utils'; import {element, elementEnd, elementStart, elementStyling, elementStylingApply, template, bind, elementProperty, text, textBinding, markDirty, listener} from '../../src/render3/instructions'; @@ -122,7 +122,7 @@ describe('discovery utils', () => { if (rf & RenderFlags.Create) { element(0, 'child'); } - }, 1, 0, 'child', ['ngIf', '']); + }, 1, 0, 'child', ['dirA', AttributeMarker.Template, 'ngIf']); elementStart(9, 'i18n'); i18n(10, MSG_DIV); elementEnd(); diff --git a/packages/core/test/render3/exports_spec.ts b/packages/core/test/render3/exports_spec.ts index 4e3b8d0ff9..01188cf90e 100644 --- a/packages/core/test/render3/exports_spec.ts +++ b/packages/core/test/render3/exports_spec.ts @@ -232,7 +232,7 @@ describe('exports', () => { if (rf & RenderFlags.Create) { elementStart(0, 'input', ['value', 'one'], ['outerInput', '']); elementEnd(); - template(2, outerTemplate, 5, 2, 'div', [AttributeMarker.Bindings, 'ngIf']); + template(2, outerTemplate, 5, 2, 'div', [AttributeMarker.Template, 'ngIf']); } if (rf & RenderFlags.Update) { elementProperty(2, 'ngIf', bind(app.outer)); @@ -246,7 +246,7 @@ describe('exports', () => { text(1); elementStart(2, 'input', ['value', 'two'], ['innerInput', '']); elementEnd(); - template(4, innerTemplate, 2, 2, 'div', [AttributeMarker.Bindings, 'ngIf']); + template(4, innerTemplate, 2, 2, 'div', [AttributeMarker.Template, 'ngIf']); } elementEnd(); } diff --git a/packages/core/test/render3/host_binding_spec.ts b/packages/core/test/render3/host_binding_spec.ts index 9bb9813c05..e74b9630fa 100644 --- a/packages/core/test/render3/host_binding_spec.ts +++ b/packages/core/test/render3/host_binding_spec.ts @@ -506,7 +506,7 @@ describe('host bindings', () => { */ const App = createComponent('parent', (rf: RenderFlags, ctx: any) => { if (rf & RenderFlags.Create) { - template(0, NgForTemplate, 2, 0, 'div', ['ngForOf', '']); + template(0, NgForTemplate, 2, 0, 'div', [AttributeMarker.Template, 'ngFor', 'ngForOf']); } if (rf & RenderFlags.Update) { elementProperty(0, 'ngForOf', bind(ctx.rows)); diff --git a/packages/core/test/render3/i18n_spec.ts b/packages/core/test/render3/i18n_spec.ts index 2a43416bbc..a23584352e 100644 --- a/packages/core/test/render3/i18n_spec.ts +++ b/packages/core/test/render3/i18n_spec.ts @@ -603,7 +603,7 @@ describe('Runtime i18n', () => { if (rf & RenderFlags.Create) { i18nStart(0, MSG_DIV, 1); elementStart(1, 'div'); - template(2, subTemplate_2, 2, 0, 'span', ['ngIf', '']); + template(2, subTemplate_2, 2, 0, 'span', [AttributeMarker.Template, 'ngIf']); elementEnd(); i18nEnd(); } @@ -632,7 +632,7 @@ describe('Runtime i18n', () => { if (rf & RenderFlags.Create) { elementStart(0, 'div'); i18nStart(1, MSG_DIV); - template(2, subTemplate_1, 3, 1, 'div', ['ngIf', '']); + template(2, subTemplate_1, 3, 1, 'div', [AttributeMarker.Template, 'ngIf']); i18nEnd(); elementEnd(); } @@ -739,7 +739,7 @@ describe('Runtime i18n', () => { if (rf & RenderFlags.Create) { elementStart(0, 'div'); i18nStart(1, MSG_DIV); - template(2, subTemplate_1, 2, 2, 'span', [3, 'ngIf']); + template(2, subTemplate_1, 2, 2, 'span', [AttributeMarker.Template, 'ngIf']); i18nEnd(); elementEnd(); } diff --git a/packages/core/test/render3/instructions_spec.ts b/packages/core/test/render3/instructions_spec.ts index f69ec88ee5..577c6e4748 100644 --- a/packages/core/test/render3/instructions_spec.ts +++ b/packages/core/test/render3/instructions_spec.ts @@ -304,12 +304,13 @@ describe('instructions', () => { describe('performance counters', () => { it('should create tViews only once for each nested level', () => { - const _c0 = ['ngFor', '', 'ngForOf', '']; + const _c0 = [AttributeMarker.Template, 'ngFor', 'ngForOf']; + const _c1 = [AttributeMarker.Template, 'ngFor', 'ngForOf']; function ToDoAppComponent_NgForOf_Template_0(rf: RenderFlags, ctx0: NgForOfContext) { if (rf & RenderFlags.Create) { elementStart(0, 'ul'); - template(1, ToDoAppComponent_NgForOf_NgForOf_Template_1, 2, 1, 'li', _c0); + template(1, ToDoAppComponent_NgForOf_NgForOf_Template_1, 2, 1, 'li', _c1); elementEnd(); } if (rf & RenderFlags.Update) { diff --git a/packages/core/test/render3/integration_spec.ts b/packages/core/test/render3/integration_spec.ts index 6e825ebd0f..bf09baa1a2 100644 --- a/packages/core/test/render3/integration_spec.ts +++ b/packages/core/test/render3/integration_spec.ts @@ -721,8 +721,7 @@ describe('render3 integration test', () => { const TestCmpt = createComponent('test-cmpt', function(rf: RenderFlags, ctx: {value: any}) { if (rf & RenderFlags.Create) { - template( - 0, ngIfTemplate, 2, 0, 'ng-template', [AttributeMarker.Bindings, 'ngIf']); + template(0, ngIfTemplate, 2, 0, 'ng-template', [AttributeMarker.Bindings, 'ngIf']); } if (rf & RenderFlags.Update) { elementProperty(0, 'ngIf', bind(ctx.value)); diff --git a/packages/core/test/render3/lifecycle_spec.ts b/packages/core/test/render3/lifecycle_spec.ts index eb9c497948..980195ba87 100644 --- a/packages/core/test/render3/lifecycle_spec.ts +++ b/packages/core/test/render3/lifecycle_spec.ts @@ -198,7 +198,7 @@ describe('lifecycles', () => { /** */ const App = createComponent('app', function(rf: RenderFlags, ctx: any) { if (rf & RenderFlags.Create) { - template(0, IfTemplate, 1, 0, 'comp', ['ngIf', '']); + template(0, IfTemplate, 1, 0, 'comp', [AttributeMarker.Template, 'ngIf']); } if (rf & RenderFlags.Update) { elementProperty(0, 'ngIf', bind(ctx.showing)); @@ -2969,8 +2969,7 @@ describe('lifecycles', () => { function conditionTpl(rf: RenderFlags, ctx: Cmpt) { if (rf & RenderFlags.Create) { - template( - 0, null, 0, 1, 'ng-template', [AttributeMarker.Bindings, 'onDestroyDirective']); + template(0, null, 0, 1, 'ng-template', [AttributeMarker.Bindings, 'onDestroyDirective']); } } diff --git a/packages/core/test/render3/pure_function_spec.ts b/packages/core/test/render3/pure_function_spec.ts index 73e3566d6b..61499cc15f 100644 --- a/packages/core/test/render3/pure_function_spec.ts +++ b/packages/core/test/render3/pure_function_spec.ts @@ -87,7 +87,9 @@ describe('array literals', () => { */ const App = createComponent('app', function(rf: RenderFlags, ctx: any) { if (rf & RenderFlags.Create) { - template(0, IfTemplate, 1, 3, 'my-comp', [AttributeMarker.Bindings, 'ngIf']); + template( + 0, IfTemplate, 1, 3, 'my-comp', + [AttributeMarker.Bindings, 'names', AttributeMarker.Template, 'ngIf']); } if (rf & RenderFlags.Update) { elementProperty(0, 'ngIf', bind(ctx.showing)); diff --git a/packages/core/test/render3/query_spec.ts b/packages/core/test/render3/query_spec.ts index eccb58954e..46c20f5376 100644 --- a/packages/core/test/render3/query_spec.ts +++ b/packages/core/test/render3/query_spec.ts @@ -1392,7 +1392,8 @@ describe('query', () => { 'cmpt', function(rf: RenderFlags, ctx: any) { if (rf & RenderFlags.Create) { - template(0, Cmpt_Template_1, 2, 0, 'ng-template', ['ngIf', '']); + template( + 0, Cmpt_Template_1, 2, 0, 'ng-template', [AttributeMarker.Bindings, 'ngIf']); } if (rf & RenderFlags.Update) { elementProperty(0, 'ngIf', bind(ctx.value)); @@ -2207,7 +2208,7 @@ describe('query', () => { function(rf: RenderFlags, ctx: any) { if (rf & RenderFlags.Create) { template( - 0, AppComponent_Template_1, 1, 0, 'div', [AttributeMarker.Bindings, 'someDir']); + 0, AppComponent_Template_1, 1, 0, 'div', [AttributeMarker.Template, 'someDir']); element(1, 'div', null, ['foo', '']); } }, @@ -2392,7 +2393,7 @@ describe('query', () => { const AppComponent = createComponent('app-component', function(rf: RenderFlags, ctx: any) { if (rf & RenderFlags.Create) { elementStart(0, 'shallow-comp'); - { template(1, IfTemplate, 2, 0, 'div', [AttributeMarker.Bindings, 'ngIf', '']); } + { template(1, IfTemplate, 2, 0, 'div', [AttributeMarker.Template, 'ngIf', '']); } elementEnd(); } if (rf & RenderFlags.Update) {