diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/GOLDEN_PARTIAL.js b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/GOLDEN_PARTIAL.js
new file mode 100644
index 0000000000..f07afcddca
--- /dev/null
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/GOLDEN_PARTIAL.js
@@ -0,0 +1,856 @@
+/****************************************************************************************************
+ * PARTIAL FILE: nested_template_context.js
+ ****************************************************************************************************/
+import { Component, NgModule } from '@angular/core';
+import * as i0 from "@angular/core";
+export class MyComponent {
+ constructor() {
+ this.component = this;
+ }
+ format(outer, middle, inner) { }
+ onClick(outer, middle, inner) { }
+}
+MyComponent.ɵfac = function MyComponent_Factory(t) { return new (t || MyComponent)(); };
+MyComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: 1, type: MyComponent, selector: "my-component", ngImport: i0, template: { source: `
+
`, isInline: true } });
+/*@__PURE__*/ (function () { i0.ɵsetClassMetadata(MyComponent, [{
+ type: Component,
+ args: [{
+ selector: 'my-component',
+ template: `
+ `
+ }]
+ }], null, null); })();
+export class MyModule {
+}
+MyModule.ɵmod = i0.ɵɵdefineNgModule({ type: MyModule });
+MyModule.ɵinj = i0.ɵɵdefineInjector({ factory: function MyModule_Factory(t) { return new (t || MyModule)(); } });
+(function () { (typeof ngJitMode === "undefined" || ngJitMode) && i0.ɵɵsetNgModuleScope(MyModule, { declarations: [MyComponent] }); })();
+/*@__PURE__*/ (function () { i0.ɵsetClassMetadata(MyModule, [{
+ type: NgModule,
+ args: [{ declarations: [MyComponent] }]
+ }], null, null); })();
+
+/****************************************************************************************************
+ * PARTIAL FILE: nested_template_context.d.ts
+ ****************************************************************************************************/
+import * as i0 from "@angular/core";
+export declare class MyComponent {
+ component: this;
+ format(outer: any, middle: any, inner: any): void;
+ onClick(outer: any, middle: any, inner: any): void;
+ static ɵfac: i0.ɵɵFactoryDef;
+ static ɵcmp: i0.ɵɵComponentDefWithMeta;
+}
+export declare class MyModule {
+ static ɵmod: i0.ɵɵNgModuleDefWithMeta;
+ static ɵinj: i0.ɵɵInjectorDef;
+}
+
+/****************************************************************************************************
+ * PARTIAL FILE: nested_template_context_many_bindings.js
+ ****************************************************************************************************/
+import { Component, NgModule } from '@angular/core';
+import * as i0 from "@angular/core";
+export class MyComponent {
+ constructor() {
+ this._data = [1, 2, 3];
+ }
+ _handleClick(d, i) { }
+}
+MyComponent.ɵfac = function MyComponent_Factory(t) { return new (t || MyComponent)(); };
+MyComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: 1, type: MyComponent, selector: "my-component", ngImport: i0, template: { source: `
+
+ `, isInline: true } });
+/*@__PURE__*/ (function () { i0.ɵsetClassMetadata(MyComponent, [{
+ type: Component,
+ args: [{
+ selector: 'my-component',
+ template: `
+
+ `
+ }]
+ }], null, null); })();
+export class MyModule {
+}
+MyModule.ɵmod = i0.ɵɵdefineNgModule({ type: MyModule });
+MyModule.ɵinj = i0.ɵɵdefineInjector({ factory: function MyModule_Factory(t) { return new (t || MyModule)(); } });
+(function () { (typeof ngJitMode === "undefined" || ngJitMode) && i0.ɵɵsetNgModuleScope(MyModule, { declarations: [MyComponent] }); })();
+/*@__PURE__*/ (function () { i0.ɵsetClassMetadata(MyModule, [{
+ type: NgModule,
+ args: [{ declarations: [MyComponent] }]
+ }], null, null); })();
+
+/****************************************************************************************************
+ * PARTIAL FILE: nested_template_context_many_bindings.d.ts
+ ****************************************************************************************************/
+import * as i0 from "@angular/core";
+export declare class MyComponent {
+ _data: number[];
+ _handleClick(d: any, i: any): void;
+ static ɵfac: i0.ɵɵFactoryDef;
+ static ɵcmp: i0.ɵɵComponentDefWithMeta;
+}
+export declare class MyModule {
+ static ɵmod: i0.ɵɵNgModuleDefWithMeta;
+ static ɵinj: i0.ɵɵInjectorDef;
+}
+
+/****************************************************************************************************
+ * PARTIAL FILE: implicit_receiver.js
+ ****************************************************************************************************/
+import { Component, NgModule } from '@angular/core';
+import * as i0 from "@angular/core";
+export class MyComponent {
+ greet(val) { }
+}
+MyComponent.ɵfac = function MyComponent_Factory(t) { return new (t || MyComponent)(); };
+MyComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: 1, type: MyComponent, selector: "my-component", ngImport: i0, template: { source: `
+
+
+ `, isInline: true } });
+/*@__PURE__*/ (function () { i0.ɵsetClassMetadata(MyComponent, [{
+ type: Component,
+ args: [{
+ selector: 'my-component',
+ template: `
+
+
+ `
+ }]
+ }], null, null); })();
+export class MyModule {
+}
+MyModule.ɵmod = i0.ɵɵdefineNgModule({ type: MyModule });
+MyModule.ɵinj = i0.ɵɵdefineInjector({ factory: function MyModule_Factory(t) { return new (t || MyModule)(); } });
+(function () { (typeof ngJitMode === "undefined" || ngJitMode) && i0.ɵɵsetNgModuleScope(MyModule, { declarations: [MyComponent] }); })();
+/*@__PURE__*/ (function () { i0.ɵsetClassMetadata(MyModule, [{
+ type: NgModule,
+ args: [{ declarations: [MyComponent] }]
+ }], null, null); })();
+
+/****************************************************************************************************
+ * PARTIAL FILE: implicit_receiver.d.ts
+ ****************************************************************************************************/
+import * as i0 from "@angular/core";
+export declare class MyComponent {
+ greet(val: any): void;
+ static ɵfac: i0.ɵɵFactoryDef;
+ static ɵcmp: i0.ɵɵComponentDefWithMeta;
+}
+export declare class MyModule {
+ static ɵmod: i0.ɵɵNgModuleDefWithMeta;
+ static ɵinj: i0.ɵɵInjectorDef;
+}
+
+/****************************************************************************************************
+ * PARTIAL FILE: ng_for_context_variables.js
+ ****************************************************************************************************/
+import { Component, NgModule } from '@angular/core';
+import * as i0 from "@angular/core";
+export class MyComponent {
+}
+MyComponent.ɵfac = function MyComponent_Factory(t) { return new (t || MyComponent)(); };
+MyComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: 1, type: MyComponent, selector: "my-component", ngImport: i0, template: { source: `
+
+ {{ i }} - {{ item }}
+
+ `, isInline: true } });
+/*@__PURE__*/ (function () { i0.ɵsetClassMetadata(MyComponent, [{
+ type: Component,
+ args: [{
+ selector: 'my-component',
+ template: `
+
+ {{ i }} - {{ item }}
+
+ `
+ }]
+ }], null, null); })();
+export class MyModule {
+}
+MyModule.ɵmod = i0.ɵɵdefineNgModule({ type: MyModule });
+MyModule.ɵinj = i0.ɵɵdefineInjector({ factory: function MyModule_Factory(t) { return new (t || MyModule)(); } });
+(function () { (typeof ngJitMode === "undefined" || ngJitMode) && i0.ɵɵsetNgModuleScope(MyModule, { declarations: [MyComponent] }); })();
+/*@__PURE__*/ (function () { i0.ɵsetClassMetadata(MyModule, [{
+ type: NgModule,
+ args: [{ declarations: [MyComponent] }]
+ }], null, null); })();
+
+/****************************************************************************************************
+ * PARTIAL FILE: ng_for_context_variables.d.ts
+ ****************************************************************************************************/
+import * as i0 from "@angular/core";
+export declare class MyComponent {
+ static ɵfac: i0.ɵɵFactoryDef;
+ static ɵcmp: i0.ɵɵComponentDefWithMeta;
+}
+export declare class MyModule {
+ static ɵmod: i0.ɵɵNgModuleDefWithMeta;
+ static ɵinj: i0.ɵɵInjectorDef;
+}
+
+/****************************************************************************************************
+ * PARTIAL FILE: ng_for_parent_context_variables.js
+ ****************************************************************************************************/
+import { Component, NgModule } from '@angular/core';
+import * as i0 from "@angular/core";
+export class MyComponent {
+}
+MyComponent.ɵfac = function MyComponent_Factory(t) { return new (t || MyComponent)(); };
+MyComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: 1, type: MyComponent, selector: "my-component", ngImport: i0, template: { source: `
+
+
+ {{ i }} - {{ item }}
+
+
`, isInline: true } });
+/*@__PURE__*/ (function () { i0.ɵsetClassMetadata(MyComponent, [{
+ type: Component,
+ args: [{
+ selector: 'my-component',
+ template: `
+
+
+ {{ i }} - {{ item }}
+
+
`
+ }]
+ }], null, null); })();
+export class MyModule {
+}
+MyModule.ɵmod = i0.ɵɵdefineNgModule({ type: MyModule });
+MyModule.ɵinj = i0.ɵɵdefineInjector({ factory: function MyModule_Factory(t) { return new (t || MyModule)(); } });
+(function () { (typeof ngJitMode === "undefined" || ngJitMode) && i0.ɵɵsetNgModuleScope(MyModule, { declarations: [MyComponent] }); })();
+/*@__PURE__*/ (function () { i0.ɵsetClassMetadata(MyModule, [{
+ type: NgModule,
+ args: [{ declarations: [MyComponent] }]
+ }], null, null); })();
+
+/****************************************************************************************************
+ * PARTIAL FILE: ng_for_parent_context_variables.d.ts
+ ****************************************************************************************************/
+import * as i0 from "@angular/core";
+export declare class MyComponent {
+ static ɵfac: i0.ɵɵFactoryDef;
+ static ɵcmp: i0.ɵɵComponentDefWithMeta;
+}
+export declare class MyModule {
+ static ɵmod: i0.ɵɵNgModuleDefWithMeta;
+ static ɵinj: i0.ɵɵInjectorDef;
+}
+
+/****************************************************************************************************
+ * PARTIAL FILE: template_context_skip.js
+ ****************************************************************************************************/
+import { Component, NgModule } from '@angular/core';
+import * as i0 from "@angular/core";
+export class MyComponent {
+}
+MyComponent.ɵfac = function MyComponent_Factory(t) { return new (t || MyComponent)(); };
+MyComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: 1, type: MyComponent, selector: "my-component", ngImport: i0, template: { source: `
+
+
+
+ {{ middle.value }} - {{ name }}
+
+
+
`, isInline: true } });
+/*@__PURE__*/ (function () { i0.ɵsetClassMetadata(MyComponent, [{
+ type: Component,
+ args: [{
+ selector: 'my-component',
+ template: `
+
+
+
+ {{ middle.value }} - {{ name }}
+
+
+
`
+ }]
+ }], null, null); })();
+export class MyModule {
+}
+MyModule.ɵmod = i0.ɵɵdefineNgModule({ type: MyModule });
+MyModule.ɵinj = i0.ɵɵdefineInjector({ factory: function MyModule_Factory(t) { return new (t || MyModule)(); } });
+(function () { (typeof ngJitMode === "undefined" || ngJitMode) && i0.ɵɵsetNgModuleScope(MyModule, { declarations: [MyComponent] }); })();
+/*@__PURE__*/ (function () { i0.ɵsetClassMetadata(MyModule, [{
+ type: NgModule,
+ args: [{ declarations: [MyComponent] }]
+ }], null, null); })();
+
+/****************************************************************************************************
+ * PARTIAL FILE: template_context_skip.d.ts
+ ****************************************************************************************************/
+import * as i0 from "@angular/core";
+export declare class MyComponent {
+ static ɵfac: i0.ɵɵFactoryDef;
+ static ɵcmp: i0.ɵɵComponentDefWithMeta;
+}
+export declare class MyModule {
+ static ɵmod: i0.ɵɵNgModuleDefWithMeta;
+ static ɵinj: i0.ɵɵInjectorDef;
+}
+
+/****************************************************************************************************
+ * PARTIAL FILE: ng_template.js
+ ****************************************************************************************************/
+import { Component, NgModule } from '@angular/core';
+import * as i0 from "@angular/core";
+export class MyComponent {
+}
+MyComponent.ɵfac = function MyComponent_Factory(t) { return new (t || MyComponent)(); };
+MyComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: 1, type: MyComponent, selector: "my-component", ngImport: i0, template: { source: `
+
+ some-content
+ `, isInline: true } });
+/*@__PURE__*/ (function () { i0.ɵsetClassMetadata(MyComponent, [{
+ type: Component,
+ args: [{
+ selector: 'my-component',
+ template: `
+
+ some-content
+ `
+ }]
+ }], null, null); })();
+export class MyModule {
+}
+MyModule.ɵmod = i0.ɵɵdefineNgModule({ type: MyModule });
+MyModule.ɵinj = i0.ɵɵdefineInjector({ factory: function MyModule_Factory(t) { return new (t || MyModule)(); } });
+(function () { (typeof ngJitMode === "undefined" || ngJitMode) && i0.ɵɵsetNgModuleScope(MyModule, { declarations: [MyComponent] }); })();
+/*@__PURE__*/ (function () { i0.ɵsetClassMetadata(MyModule, [{
+ type: NgModule,
+ args: [{ declarations: [MyComponent] }]
+ }], null, null); })();
+
+/****************************************************************************************************
+ * PARTIAL FILE: ng_template.d.ts
+ ****************************************************************************************************/
+import * as i0 from "@angular/core";
+export declare class MyComponent {
+ static ɵfac: i0.ɵɵFactoryDef;
+ static ɵcmp: i0.ɵɵComponentDefWithMeta;
+}
+export declare class MyModule {
+ static ɵmod: i0.ɵɵNgModuleDefWithMeta;
+ static ɵinj: i0.ɵɵInjectorDef;
+}
+
+/****************************************************************************************************
+ * PARTIAL FILE: ng_template_local_ref.js
+ ****************************************************************************************************/
+import { Component, NgModule } from '@angular/core';
+import * as i0 from "@angular/core";
+export class MyComponent {
+}
+MyComponent.ɵfac = function MyComponent_Factory(t) { return new (t || MyComponent)(); };
+MyComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: 1, type: MyComponent, selector: "my-component", ngImport: i0, template: { source: 'some-content', isInline: true } });
+/*@__PURE__*/ (function () { i0.ɵsetClassMetadata(MyComponent, [{
+ type: Component,
+ args: [{
+ selector: 'my-component',
+ template: 'some-content',
+ }]
+ }], null, null); })();
+export class MyModule {
+}
+MyModule.ɵmod = i0.ɵɵdefineNgModule({ type: MyModule });
+MyModule.ɵinj = i0.ɵɵdefineInjector({ factory: function MyModule_Factory(t) { return new (t || MyModule)(); } });
+(function () { (typeof ngJitMode === "undefined" || ngJitMode) && i0.ɵɵsetNgModuleScope(MyModule, { declarations: [MyComponent] }); })();
+/*@__PURE__*/ (function () { i0.ɵsetClassMetadata(MyModule, [{
+ type: NgModule,
+ args: [{ declarations: [MyComponent] }]
+ }], null, null); })();
+
+/****************************************************************************************************
+ * PARTIAL FILE: ng_template_local_ref.d.ts
+ ****************************************************************************************************/
+import * as i0 from "@angular/core";
+export declare class MyComponent {
+ static ɵfac: i0.ɵɵFactoryDef;
+ static ɵcmp: i0.ɵɵComponentDefWithMeta;
+}
+export declare class MyModule {
+ static ɵmod: i0.ɵɵNgModuleDefWithMeta;
+ static ɵinj: i0.ɵɵInjectorDef;
+}
+
+/****************************************************************************************************
+ * PARTIAL FILE: ng_template_output.js
+ ****************************************************************************************************/
+import { Component, NgModule } from '@angular/core';
+import * as i0 from "@angular/core";
+export class MyComponent {
+}
+MyComponent.ɵfac = function MyComponent_Factory(t) { return new (t || MyComponent)(); };
+MyComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: 1, type: MyComponent, selector: "my-component", ngImport: i0, template: { source: '', isInline: true } });
+/*@__PURE__*/ (function () { i0.ɵsetClassMetadata(MyComponent, [{
+ type: Component,
+ args: [{
+ selector: 'my-component',
+ template: '',
+ }]
+ }], null, null); })();
+export class MyModule {
+}
+MyModule.ɵmod = i0.ɵɵdefineNgModule({ type: MyModule });
+MyModule.ɵinj = i0.ɵɵdefineInjector({ factory: function MyModule_Factory(t) { return new (t || MyModule)(); } });
+(function () { (typeof ngJitMode === "undefined" || ngJitMode) && i0.ɵɵsetNgModuleScope(MyModule, { declarations: [MyComponent] }); })();
+/*@__PURE__*/ (function () { i0.ɵsetClassMetadata(MyModule, [{
+ type: NgModule,
+ args: [{ declarations: [MyComponent] }]
+ }], null, null); })();
+
+/****************************************************************************************************
+ * PARTIAL FILE: ng_template_output.d.ts
+ ****************************************************************************************************/
+import * as i0 from "@angular/core";
+export declare class MyComponent {
+ static ɵfac: i0.ɵɵFactoryDef;
+ static ɵcmp: i0.ɵɵComponentDefWithMeta;
+}
+export declare class MyModule {
+ static ɵmod: i0.ɵɵNgModuleDefWithMeta;
+ static ɵinj: i0.ɵɵInjectorDef;
+}
+
+/****************************************************************************************************
+ * PARTIAL FILE: ng_template_interpolated_prop.js
+ ****************************************************************************************************/
+import { Component, Directive, Input } from '@angular/core';
+import * as i0 from "@angular/core";
+class WithInput {
+ constructor() {
+ this.dir = '';
+ }
+}
+WithInput.ɵfac = function WithInput_Factory(t) { return new (t || WithInput)(); };
+WithInput.ɵdir = i0.ɵɵngDeclareDirective({ version: 1, type: WithInput, selector: "[dir]", inputs: { dir: "dir" }, ngImport: i0 });
+/*@__PURE__*/ (function () { i0.ɵsetClassMetadata(WithInput, [{
+ type: Directive,
+ args: [{ selector: '[dir]' }]
+ }], null, { dir: [{
+ type: Input
+ }] }); })();
+export class TestComp {
+ constructor() {
+ this.message = 'Hello';
+ }
+}
+TestComp.ɵfac = function TestComp_Factory(t) { return new (t || TestComp)(); };
+TestComp.ɵcmp = i0.ɵɵngDeclareComponent({ version: 1, type: TestComp, selector: "my-app", ngImport: i0, template: { source: '', isInline: true } });
+/*@__PURE__*/ (function () { i0.ɵsetClassMetadata(TestComp, [{
+ type: Component,
+ args: [{
+ selector: 'my-app',
+ template: '',
+ }]
+ }], null, null); })();
+
+/****************************************************************************************************
+ * PARTIAL FILE: ng_template_interpolated_prop.d.ts
+ ****************************************************************************************************/
+import * as i0 from "@angular/core";
+export declare class TestComp {
+ message: string;
+ static ɵfac: i0.ɵɵFactoryDef;
+ static ɵcmp: i0.ɵɵComponentDefWithMeta;
+}
+
+/****************************************************************************************************
+ * PARTIAL FILE: ng_template_interpolated_prop_with_structural_directive.js
+ ****************************************************************************************************/
+import { Component, Directive, Input } from '@angular/core';
+import * as i0 from "@angular/core";
+class WithInput {
+ constructor() {
+ this.dir = '';
+ }
+}
+WithInput.ɵfac = function WithInput_Factory(t) { return new (t || WithInput)(); };
+WithInput.ɵdir = i0.ɵɵngDeclareDirective({ version: 1, type: WithInput, selector: "[dir]", inputs: { dir: "dir" }, ngImport: i0 });
+/*@__PURE__*/ (function () { i0.ɵsetClassMetadata(WithInput, [{
+ type: Directive,
+ args: [{ selector: '[dir]' }]
+ }], null, { dir: [{
+ type: Input
+ }] }); })();
+export class TestComp {
+ constructor() {
+ this.message = 'Hello';
+ }
+}
+TestComp.ɵfac = function TestComp_Factory(t) { return new (t || TestComp)(); };
+TestComp.ɵcmp = i0.ɵɵngDeclareComponent({ version: 1, type: TestComp, selector: "my-app", ngImport: i0, template: { source: '', isInline: true } });
+/*@__PURE__*/ (function () { i0.ɵsetClassMetadata(TestComp, [{
+ type: Component,
+ args: [{
+ selector: 'my-app',
+ template: '',
+ }]
+ }], null, null); })();
+
+/****************************************************************************************************
+ * PARTIAL FILE: ng_template_interpolated_prop_with_structural_directive.d.ts
+ ****************************************************************************************************/
+import * as i0 from "@angular/core";
+export declare class TestComp {
+ message: string;
+ static ɵfac: i0.ɵɵFactoryDef;
+ static ɵcmp: i0.ɵɵComponentDefWithMeta;
+}
+
+/****************************************************************************************************
+ * PARTIAL FILE: unique_template_function_names.js
+ ****************************************************************************************************/
+import { Component, NgModule } from '@angular/core';
+import * as i0 from "@angular/core";
+export class AComponent {
+ constructor() {
+ this.items = [4, 2];
+ }
+}
+AComponent.ɵfac = function AComponent_Factory(t) { return new (t || AComponent)(); };
+AComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: 1, type: AComponent, selector: "a-component", ngImport: i0, template: { source: `
+
+
less than 10
+
less than 10
+
+
+ `, isInline: true } });
+/*@__PURE__*/ (function () { i0.ɵsetClassMetadata(AComponent, [{
+ type: Component,
+ args: [{
+ selector: 'a-component',
+ template: `
+
+
less than 10
+
less than 10
+
+
+ `,
+ }]
+ }], null, null); })();
+export class AModule {
+}
+AModule.ɵmod = i0.ɵɵdefineNgModule({ type: AModule });
+AModule.ɵinj = i0.ɵɵdefineInjector({ factory: function AModule_Factory(t) { return new (t || AModule)(); } });
+(function () { (typeof ngJitMode === "undefined" || ngJitMode) && i0.ɵɵsetNgModuleScope(AModule, { declarations: [AComponent] }); })();
+/*@__PURE__*/ (function () { i0.ɵsetClassMetadata(AModule, [{
+ type: NgModule,
+ args: [{ declarations: [AComponent] }]
+ }], null, null); })();
+export class BComponent {
+ constructor() {
+ this.items = [
+ { subitems: [1, 3] },
+ { subitems: [3, 7] },
+ ];
+ }
+}
+BComponent.ɵfac = function BComponent_Factory(t) { return new (t || BComponent)(); };
+BComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: 1, type: BComponent, selector: "b-component", ngImport: i0, template: { source: `
+
+
+ less than 10
+ less than 10
+
+
+ less than 10
+
+
+
+ `, isInline: true } });
+/*@__PURE__*/ (function () { i0.ɵsetClassMetadata(BComponent, [{
+ type: Component,
+ args: [{
+ selector: 'b-component',
+ template: `
+
+
+ less than 10
+ less than 10
+
+
+ less than 10
+
+
+
+ `,
+ }]
+ }], null, null); })();
+export class BModule {
+}
+BModule.ɵmod = i0.ɵɵdefineNgModule({ type: BModule });
+BModule.ɵinj = i0.ɵɵdefineInjector({ factory: function BModule_Factory(t) { return new (t || BModule)(); } });
+(function () { (typeof ngJitMode === "undefined" || ngJitMode) && i0.ɵɵsetNgModuleScope(BModule, { declarations: [BComponent] }); })();
+/*@__PURE__*/ (function () { i0.ɵsetClassMetadata(BModule, [{
+ type: NgModule,
+ args: [{ declarations: [BComponent] }]
+ }], null, null); })();
+
+/****************************************************************************************************
+ * PARTIAL FILE: unique_template_function_names.d.ts
+ ****************************************************************************************************/
+import * as i0 from "@angular/core";
+export declare class AComponent {
+ items: number[];
+ static ɵfac: i0.ɵɵFactoryDef;
+ static ɵcmp: i0.ɵɵComponentDefWithMeta;
+}
+export declare class AModule {
+ static ɵmod: i0.ɵɵNgModuleDefWithMeta;
+ static ɵinj: i0.ɵɵInjectorDef;
+}
+export declare class BComponent {
+ items: {
+ subitems: number[];
+ }[];
+ static ɵfac: i0.ɵɵFactoryDef;
+ static ɵcmp: i0.ɵɵComponentDefWithMeta;
+}
+export declare class BModule {
+ static ɵmod: i0.ɵɵNgModuleDefWithMeta;
+ static ɵinj: i0.ɵɵInjectorDef;
+}
+
+/****************************************************************************************************
+ * PARTIAL FILE: unique_template_function_names_ng_content.js
+ ****************************************************************************************************/
+import { Component, NgModule } from '@angular/core';
+import * as i0 from "@angular/core";
+export class AComponent {
+ constructor() {
+ this.show = true;
+ }
+}
+AComponent.ɵfac = function AComponent_Factory(t) { return new (t || AComponent)(); };
+AComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: 1, type: AComponent, selector: "a-component", ngImport: i0, template: { source: `
+
+ `, isInline: true } });
+/*@__PURE__*/ (function () { i0.ɵsetClassMetadata(AComponent, [{
+ type: Component,
+ args: [{
+ selector: 'a-component',
+ template: `
+
+ `,
+ }]
+ }], null, null); })();
+export class BComponent {
+ constructor() {
+ this.show = true;
+ }
+}
+BComponent.ɵfac = function BComponent_Factory(t) { return new (t || BComponent)(); };
+BComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: 1, type: BComponent, selector: "b-component", ngImport: i0, template: { source: `
+
+ `, isInline: true } });
+/*@__PURE__*/ (function () { i0.ɵsetClassMetadata(BComponent, [{
+ type: Component,
+ args: [{
+ selector: 'b-component',
+ template: `
+
+ `,
+ }]
+ }], null, null); })();
+export class AModule {
+}
+AModule.ɵmod = i0.ɵɵdefineNgModule({ type: AModule });
+AModule.ɵinj = i0.ɵɵdefineInjector({ factory: function AModule_Factory(t) { return new (t || AModule)(); } });
+(function () { (typeof ngJitMode === "undefined" || ngJitMode) && i0.ɵɵsetNgModuleScope(AModule, { declarations: [AComponent, BComponent] }); })();
+/*@__PURE__*/ (function () { i0.ɵsetClassMetadata(AModule, [{
+ type: NgModule,
+ args: [{ declarations: [AComponent, BComponent] }]
+ }], null, null); })();
+
+/****************************************************************************************************
+ * PARTIAL FILE: unique_template_function_names_ng_content.d.ts
+ ****************************************************************************************************/
+import * as i0 from "@angular/core";
+export declare class AComponent {
+ show: boolean;
+ static ɵfac: i0.ɵɵFactoryDef;
+ static ɵcmp: i0.ɵɵComponentDefWithMeta;
+}
+export declare class BComponent {
+ show: boolean;
+ static ɵfac: i0.ɵɵFactoryDef;
+ static ɵcmp: i0.ɵɵComponentDefWithMeta;
+}
+export declare class AModule {
+ static ɵmod: i0.ɵɵNgModuleDefWithMeta;
+ static ɵinj: i0.ɵɵInjectorDef;
+}
+
+/****************************************************************************************************
+ * PARTIAL FILE: unique_listener_function_names.js
+ ****************************************************************************************************/
+import { Component, NgModule } from '@angular/core';
+import * as i0 from "@angular/core";
+export class MyComponent {
+ constructor() {
+ this.items = [4, 2];
+ }
+}
+MyComponent.ɵfac = function MyComponent_Factory(t) { return new (t || MyComponent)(); };
+MyComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: 1, type: MyComponent, selector: "my-component", ngImport: i0, template: { source: `
+
+
{{ item }}
+
{{ item }}
+
+
+ `, isInline: true } });
+/*@__PURE__*/ (function () { i0.ɵsetClassMetadata(MyComponent, [{
+ type: Component,
+ args: [{
+ selector: 'my-component',
+ template: `
+
+
{{ item }}
+
{{ item }}
+
+
+ `,
+ }]
+ }], null, null); })();
+export class MyModule {
+}
+MyModule.ɵmod = i0.ɵɵdefineNgModule({ type: MyModule });
+MyModule.ɵinj = i0.ɵɵdefineInjector({ factory: function MyModule_Factory(t) { return new (t || MyModule)(); } });
+(function () { (typeof ngJitMode === "undefined" || ngJitMode) && i0.ɵɵsetNgModuleScope(MyModule, { declarations: [MyComponent] }); })();
+/*@__PURE__*/ (function () { i0.ɵsetClassMetadata(MyModule, [{
+ type: NgModule,
+ args: [{ declarations: [MyComponent] }]
+ }], null, null); })();
+
+/****************************************************************************************************
+ * PARTIAL FILE: unique_listener_function_names.d.ts
+ ****************************************************************************************************/
+import * as i0 from "@angular/core";
+export declare class MyComponent {
+ items: number[];
+ static ɵfac: i0.ɵɵFactoryDef;
+ static ɵcmp: i0.ɵɵComponentDefWithMeta;
+}
+export declare class MyModule {
+ static ɵmod: i0.ɵɵNgModuleDefWithMeta;
+ static ɵinj: i0.ɵɵInjectorDef;
+}
+
+/****************************************************************************************************
+ * PARTIAL FILE: template_binding_pipe.js
+ ****************************************************************************************************/
+import { Component, NgModule } from '@angular/core';
+import * as i0 from "@angular/core";
+export class MyComponent {
+}
+MyComponent.ɵfac = function MyComponent_Factory(t) { return new (t || MyComponent)(); };
+MyComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: 1, type: MyComponent, selector: "my-component", ngImport: i0, template: { source: ``, isInline: true } });
+/*@__PURE__*/ (function () { i0.ɵsetClassMetadata(MyComponent, [{
+ type: Component,
+ args: [{
+ selector: 'my-component',
+ template: ``,
+ }]
+ }], null, null); })();
+export class MyModule {
+}
+MyModule.ɵmod = i0.ɵɵdefineNgModule({ type: MyModule });
+MyModule.ɵinj = i0.ɵɵdefineInjector({ factory: function MyModule_Factory(t) { return new (t || MyModule)(); } });
+(function () { (typeof ngJitMode === "undefined" || ngJitMode) && i0.ɵɵsetNgModuleScope(MyModule, { declarations: [MyComponent] }); })();
+/*@__PURE__*/ (function () { i0.ɵsetClassMetadata(MyModule, [{
+ type: NgModule,
+ args: [{ declarations: [MyComponent] }]
+ }], null, null); })();
+
+/****************************************************************************************************
+ * PARTIAL FILE: template_binding_pipe.d.ts
+ ****************************************************************************************************/
+import * as i0 from "@angular/core";
+export declare class MyComponent {
+ static ɵfac: i0.ɵɵFactoryDef;
+ static ɵcmp: i0.ɵɵComponentDefWithMeta;
+}
+export declare class MyModule {
+ static ɵmod: i0.ɵɵNgModuleDefWithMeta;
+ static ɵinj: i0.ɵɵInjectorDef;
+}
+
+/****************************************************************************************************
+ * PARTIAL FILE: nested_ternary_operation.js
+ ****************************************************************************************************/
+import { Component, NgModule } from '@angular/core';
+import * as i0 from "@angular/core";
+export class MyComponent {
+}
+MyComponent.ɵfac = function MyComponent_Factory(t) { return new (t || MyComponent)(); };
+MyComponent.ɵcmp = i0.ɵɵngDeclareComponent({ version: 1, type: MyComponent, selector: "my-component", ngImport: i0, template: { source: `
+ {{a?.b ? 1 : 2 }}`, isInline: true } });
+/*@__PURE__*/ (function () { i0.ɵsetClassMetadata(MyComponent, [{
+ type: Component,
+ args: [{
+ selector: 'my-component',
+ template: `
+ {{a?.b ? 1 : 2 }}`,
+ }]
+ }], null, null); })();
+export class MyModule {
+}
+MyModule.ɵmod = i0.ɵɵdefineNgModule({ type: MyModule });
+MyModule.ɵinj = i0.ɵɵdefineInjector({ factory: function MyModule_Factory(t) { return new (t || MyModule)(); } });
+(function () { (typeof ngJitMode === "undefined" || ngJitMode) && i0.ɵɵsetNgModuleScope(MyModule, { declarations: [MyComponent] }); })();
+/*@__PURE__*/ (function () { i0.ɵsetClassMetadata(MyModule, [{
+ type: NgModule,
+ args: [{ declarations: [MyComponent] }]
+ }], null, null); })();
+
+/****************************************************************************************************
+ * PARTIAL FILE: nested_ternary_operation.d.ts
+ ****************************************************************************************************/
+import * as i0 from "@angular/core";
+export declare class MyComponent {
+ static ɵfac: i0.ɵɵFactoryDef;
+ static ɵcmp: i0.ɵɵComponentDefWithMeta;
+}
+export declare class MyModule {
+ static ɵmod: i0.ɵɵNgModuleDefWithMeta;
+ static ɵinj: i0.ɵɵInjectorDef;
+}
+
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/TEST_CASES.json b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/TEST_CASES.json
new file mode 100644
index 0000000000..a8ee6599f7
--- /dev/null
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/TEST_CASES.json
@@ -0,0 +1,274 @@
+{
+ "$schema": "../test_case_schema.json",
+ "cases": [
+ {
+ "description": "should correctly bind to context in nested template",
+ "inputFiles": [
+ "nested_template_context.ts"
+ ],
+ "expectations": [
+ {
+ "files": [
+ {
+ "expected": "nested_template_context_template.js",
+ "generated": "nested_template_context.js"
+ }
+ ],
+ "failureMessage": "Incorrect template"
+ }
+ ]
+ },
+ {
+ "description": "should correctly bind to context in nested template with many bindings",
+ "inputFiles": [
+ "nested_template_context_many_bindings.ts"
+ ],
+ "expectations": [
+ {
+ "files": [
+ {
+ "expected": "nested_template_context_many_bindings_template.js",
+ "generated": "nested_template_context_many_bindings.js"
+ }
+ ],
+ "failureMessage": "Incorrect template"
+ }
+ ]
+ },
+ {
+ "description": "should correctly bind to implicit receiver in template",
+ "inputFiles": [
+ "implicit_receiver.ts"
+ ],
+ "expectations": [
+ {
+ "files": [
+ {
+ "expected": "implicit_receiver_template.js",
+ "generated": "implicit_receiver.js"
+ }
+ ],
+ "failureMessage": "Incorrect template"
+ }
+ ]
+ },
+ {
+ "description": "should support ngFor context variables",
+ "inputFiles": [
+ "ng_for_context_variables.ts"
+ ],
+ "expectations": [
+ {
+ "files": [
+ {
+ "expected": "ng_for_context_variables_template.js",
+ "generated": "ng_for_context_variables.js"
+ }
+ ],
+ "failureMessage": "Incorrect template"
+ }
+ ]
+ },
+ {
+ "description": "should support ngFor context variables in parent views",
+ "inputFiles": [
+ "ng_for_parent_context_variables.ts"
+ ],
+ "expectations": [
+ {
+ "files": [
+ {
+ "expected": "ng_for_parent_context_variables_template.js",
+ "generated": "ng_for_parent_context_variables.js"
+ }
+ ],
+ "failureMessage": "Incorrect template"
+ }
+ ]
+ },
+ {
+ "description": "should correctly skip contexts as needed",
+ "inputFiles": [
+ "template_context_skip.ts"
+ ],
+ "expectations": [
+ {
+ "files": [
+ {
+ "expected": "template_context_skip_template.js",
+ "generated": "template_context_skip.js"
+ }
+ ],
+ "failureMessage": "Incorrect template"
+ }
+ ]
+ },
+ {
+ "description": "should support ",
+ "inputFiles": [
+ "ng_template.ts"
+ ],
+ "expectations": [
+ {
+ "files": [
+ {
+ "expected": "ng_template_template.js",
+ "generated": "ng_template.js"
+ }
+ ],
+ "failureMessage": "Incorrect template"
+ }
+ ]
+ },
+ {
+ "description": "should support local refs on ",
+ "inputFiles": [
+ "ng_template_local_ref.ts"
+ ],
+ "expectations": [
+ {
+ "files": [
+ {
+ "expected": "ng_template_local_ref_template.js",
+ "generated": "ng_template_local_ref.js"
+ }
+ ],
+ "failureMessage": "Incorrect template"
+ }
+ ]
+ },
+ {
+ "description": "should support directive outputs on ",
+ "inputFiles": [
+ "ng_template_output.ts"
+ ],
+ "expectations": [
+ {
+ "files": [
+ {
+ "expected": "ng_template_output_template.js",
+ "generated": "ng_template_output.js"
+ }
+ ],
+ "failureMessage": "Incorrect template"
+ }
+ ]
+ },
+ {
+ "description": "should allow directive inputs as an interpolated prop on ",
+ "inputFiles": [
+ "ng_template_interpolated_prop.ts"
+ ],
+ "expectations": [
+ {
+ "files": [
+ {
+ "expected": "ng_template_interpolated_prop_template.js",
+ "generated": "ng_template_interpolated_prop.js"
+ }
+ ],
+ "failureMessage": "Incorrect template"
+ }
+ ]
+ },
+ {
+ "description": "should allow directive inputs as an interpolated prop on (with structural directives)",
+ "inputFiles": [
+ "ng_template_interpolated_prop_with_structural_directive.ts"
+ ],
+ "expectations": [
+ {
+ "files": [
+ {
+ "expected": "ng_template_interpolated_prop_with_structural_directive_inner_template.js",
+ "generated": "ng_template_interpolated_prop_with_structural_directive.js"
+ }
+ ],
+ "failureMessage": "Incorrect inner template"
+ },
+ {
+ "files": [
+ {
+ "expected": "ng_template_interpolated_prop_with_structural_directive_outer_template.js",
+ "generated": "ng_template_interpolated_prop_with_structural_directive.js"
+ }
+ ],
+ "failureMessage": "Incorrect outer template"
+ }
+ ]
+ },
+ {
+ "description": "should create unique template function names even for similar nested template structures",
+ "inputFiles": [
+ "unique_template_function_names.ts"
+ ],
+ "expectations": [
+ {
+ "extraChecks": [
+ ["verifyUniqueFunctions", "Template", 16]
+ ]
+ }
+ ]
+ },
+ {
+ "description": "should create unique template function names for ng-content templates",
+ "inputFiles": [
+ "unique_template_function_names_ng_content.ts"
+ ],
+ "expectations": [
+ {
+ "extraChecks": [
+ ["verifyUniqueFunctions", "Template", 4]
+ ]
+ }
+ ]
+ },
+ {
+ "description": "should create unique listener function names even for similar nested template structures",
+ "inputFiles": [
+ "unique_listener_function_names.ts"
+ ],
+ "expectations": [
+ {
+ "extraChecks": [
+ ["verifyUniqueFunctions", "listener", 3]
+ ]
+ }
+ ]
+ },
+ {
+ "description": "should support pipes in template bindings",
+ "inputFiles": [
+ "template_binding_pipe.ts"
+ ],
+ "expectations": [
+ {
+ "files": [
+ {
+ "expected": "template_binding_pipe_template.js",
+ "generated": "template_binding_pipe.js"
+ }
+ ],
+ "failureMessage": "Incorrect template"
+ }
+ ]
+ },
+ {
+ "description": "should safely nest ternary operations",
+ "inputFiles": [
+ "nested_ternary_operation.ts"
+ ],
+ "expectations": [
+ {
+ "files": [
+ {
+ "expected": "nested_ternary_operation_template.js",
+ "generated": "nested_ternary_operation.js"
+ }
+ ],
+ "failureMessage": "Incorrect template"
+ }
+ ]
+ }
+ ]
+}
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/implicit_receiver.ts b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/implicit_receiver.ts
new file mode 100644
index 0000000000..4be1a82fba
--- /dev/null
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/implicit_receiver.ts
@@ -0,0 +1,16 @@
+import {Component, NgModule} from '@angular/core';
+
+@Component({
+ selector: 'my-component',
+ template: `
+
+
+ `
+})
+export class MyComponent {
+ greet(val: any) {}
+}
+
+@NgModule({declarations: [MyComponent]})
+export class MyModule {
+}
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/implicit_receiver_template.js b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/implicit_receiver_template.js
new file mode 100644
index 0000000000..b1f4afd403
--- /dev/null
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/implicit_receiver_template.js
@@ -0,0 +1,21 @@
+function MyComponent_div_0_Template(rf, ctx) {
+ if (rf & 1) {
+ const $_r2$ = i0.ɵɵgetCurrentView();
+ $r3$.ɵɵelementStart(0, "div", 2);
+ $r3$.ɵɵlistener("click", function MyComponent_div_0_Template_div_click_0_listener() {
+ i0.ɵɵrestoreView($_r2$);
+ const $ctx_r1$ = i0.ɵɵnextContext();
+ return $ctx_r1$.greet($ctx_r1$);
+ });
+ $r3$.ɵɵelementEnd();
+ }
+}
+…
+function MyComponent_div_1_Template(rf, ctx) {
+ if (rf & 1) {
+ $r3$.ɵɵelement(0, "div", 3);
+ } if (rf & 2) {
+ const $ctx_0$ = i0.ɵɵnextContext();
+ $r3$.ɵɵproperty("id", $ctx_0$);
+ }
+}
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/nested_template_context.ts b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/nested_template_context.ts
new file mode 100644
index 0000000000..64212fdb46
--- /dev/null
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/nested_template_context.ts
@@ -0,0 +1,25 @@
+import {Component, NgModule} from '@angular/core';
+
+@Component({
+ selector: 'my-component',
+ template: `
+ `
+})
+export class MyComponent {
+ component = this;
+ format(outer: any, middle: any, inner: any) {}
+ onClick(outer: any, middle: any, inner: any) {}
+}
+
+@NgModule({declarations: [MyComponent]})
+export class MyModule {
+}
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/nested_template_context_many_bindings.ts b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/nested_template_context_many_bindings.ts
new file mode 100644
index 0000000000..dd14a3a7d6
--- /dev/null
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/nested_template_context_many_bindings.ts
@@ -0,0 +1,16 @@
+import {Component, NgModule} from '@angular/core';
+
+@Component({
+ selector: 'my-component',
+ template: `
+
+ `
+})
+export class MyComponent {
+ _data = [1, 2, 3];
+ _handleClick(d: any, i: any) {}
+}
+
+@NgModule({declarations: [MyComponent]})
+export class MyModule {
+}
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/nested_template_context_many_bindings_template.js b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/nested_template_context_many_bindings_template.js
new file mode 100644
index 0000000000..4a6ef26552
--- /dev/null
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/nested_template_context_many_bindings_template.js
@@ -0,0 +1,27 @@
+function MyComponent_div_0_Template(rf, ctx) {
+ if (rf & 1) {
+ const $s$ = $r3$.ɵɵgetCurrentView();
+ $r3$.ɵɵelementStart(0, "div", 1);
+ $r3$.ɵɵlistener("click", function MyComponent_div_0_Template_div_click_0_listener() {
+ $r3$.ɵɵrestoreView($s$);
+ const $d$ = ctx.$implicit;
+ const $i$ = ctx.index;
+ const $comp$ = $r3$.ɵɵnextContext();
+ return $comp$._handleClick($d$, $i$);
+ });
+ $r3$.ɵɵelementEnd();
+ }
+}
+…
+consts: [
+ [__AttributeMarker.Bindings__, "click", __AttributeMarker.Template__, "ngFor", "ngForOf"],
+ [__AttributeMarker.Bindings__, "click"]
+],
+template: function MyComponent_Template(rf, ctx) {
+ if (rf & 1) {
+ $r3$.ɵɵtemplate(0, MyComponent_div_0_Template, 1, 0, "div", 0);
+ }
+ if (rf & 2) {
+ $r3$.ɵɵproperty("ngForOf", ctx._data);
+ }
+}
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/nested_template_context_template.js b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/nested_template_context_template.js
new file mode 100644
index 0000000000..2665d80207
--- /dev/null
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/nested_template_context_template.js
@@ -0,0 +1,66 @@
+function MyComponent_ul_0_li_1_div_1_Template(rf, ctx) {
+ if (rf & 1) {
+ const $s$ = $i0$.ɵɵgetCurrentView();
+ $i0$.ɵɵelementStart(0, "div", 2);
+ $i0$.ɵɵlistener("click", function MyComponent_ul_0_li_1_div_1_Template_div_click_0_listener(){
+ $i0$.ɵɵrestoreView($s$);
+ const $inner$ = ctx.$implicit;
+ const $middle$ = $i0$.ɵɵnextContext().$implicit;
+ const $outer$ = $i0$.ɵɵnextContext().$implicit;
+ const $myComp$ = $i0$.ɵɵnextContext();
+ return $myComp$.onClick($outer$, $middle$, $inner$);
+ });
+ $i0$.ɵɵtext(1);
+ $i0$.ɵɵelementEnd();
+ }
+
+ if (rf & 2) {
+ const $inner1$ = ctx.$implicit;
+ const $middle1$ = $i0$.ɵɵnextContext().$implicit;
+ const $outer1$ = $i0$.ɵɵnextContext().$implicit;
+ const $myComp1$ = $i0$.ɵɵnextContext();
+ $i0$.ɵɵproperty("title", $myComp1$.format($outer1$, $middle1$, $inner1$, $myComp1$.component));
+ $r3$.ɵɵadvance(1);
+ $i0$.ɵɵtextInterpolate1(" ", $myComp1$.format($outer1$, $middle1$, $inner1$, $myComp1$.component), " ");
+ }
+}
+
+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", 1);
+ $i0$.ɵɵelementEnd();
+ }
+ if (rf & 2) {
+ const $myComp2$ = $i0$.ɵɵnextContext(2);
+ $r3$.ɵɵadvance(1);
+ $i0$.ɵɵproperty("ngForOf", $myComp2$.items);
+ }
+}
+
+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", 0);
+ $i0$.ɵɵelementEnd();
+ }
+ if (rf & 2) {
+ const $outer2$ = ctx.$implicit;
+ $r3$.ɵɵadvance(1);
+ $i0$.ɵɵproperty("ngForOf", $outer2$.items);
+ }
+}
+…
+consts: [
+ [__AttributeMarker.Template__, "ngFor", "ngForOf"],
+ [__AttributeMarker.Bindings__, "title", "click", __AttributeMarker.Template__, "ngFor", "ngForOf"],
+ [__AttributeMarker.Bindings__, "title", "click"]
+],
+template:function MyComponent_Template(rf, ctx){
+ if (rf & 1) {
+ $i0$.ɵɵtemplate(0, MyComponent_ul_0_Template, 2, 1, "ul", 0);
+ }
+ if (rf & 2) {
+ $i0$.ɵɵproperty("ngForOf", ctx.items);
+ }
+}
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/nested_ternary_operation.ts b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/nested_ternary_operation.ts
new file mode 100644
index 0000000000..f166397e08
--- /dev/null
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/nested_ternary_operation.ts
@@ -0,0 +1,13 @@
+import {Component, NgModule} from '@angular/core';
+
+@Component({
+ selector: 'my-component',
+ template: `
+ {{a?.b ? 1 : 2 }}`,
+})
+export class MyComponent {
+}
+
+@NgModule({declarations: [MyComponent]})
+export class MyModule {
+}
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/nested_ternary_operation_template.js b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/nested_ternary_operation_template.js
new file mode 100644
index 0000000000..4d0c6da4ae
--- /dev/null
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/nested_ternary_operation_template.js
@@ -0,0 +1,2 @@
+…
+i0.ɵɵtextInterpolate1(" ", (ctx.a == null ? null : ctx.a.b) ? 1 : 2, "")
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_for_context_variables.ts b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_for_context_variables.ts
new file mode 100644
index 0000000000..e49a0794b3
--- /dev/null
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_for_context_variables.ts
@@ -0,0 +1,16 @@
+import {Component, NgModule} from '@angular/core';
+
+@Component({
+ selector: 'my-component',
+ template: `
+
+ {{ i }} - {{ item }}
+
+ `
+})
+export class MyComponent {
+}
+
+@NgModule({declarations: [MyComponent]})
+export class MyModule {
+}
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_for_context_variables_template.js b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_for_context_variables_template.js
new file mode 100644
index 0000000000..1d88611767
--- /dev/null
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_for_context_variables_template.js
@@ -0,0 +1,23 @@
+function MyComponent_span_0_Template(rf, ctx) {
+ if (rf & 1) {
+ $i0$.ɵɵelementStart(0, "span");
+ $i0$.ɵɵtext(1);
+ $i0$.ɵɵelementEnd();
+ }
+ if (rf & 2) {
+ const $item$ = ctx.$implicit;
+ const $i$ = ctx.index;
+ $r3$.ɵɵadvance(1);
+ $i0$.ɵɵtextInterpolate2(" ", $i$, " - ", $item$, " ");
+ }
+}
+…
+consts: [[__AttributeMarker.Template__, "ngFor", "ngForOf"]],
+template:function MyComponent_Template(rf, ctx){
+ if (rf & 1) {
+ $i0$.ɵɵtemplate(0, MyComponent_span_0_Template, 2, 2, "span", 0);
+ }
+ if (rf & 2) {
+ $i0$.ɵɵproperty("ngForOf", ctx.items);
+ }
+}
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_for_parent_context_variables.ts b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_for_parent_context_variables.ts
new file mode 100644
index 0000000000..164978f4ad
--- /dev/null
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_for_parent_context_variables.ts
@@ -0,0 +1,17 @@
+import {Component, NgModule} from '@angular/core';
+
+@Component({
+ selector: 'my-component',
+ template: `
+
+
+ {{ i }} - {{ item }}
+
+
`
+})
+export class MyComponent {
+}
+
+@NgModule({declarations: [MyComponent]})
+export class MyModule {
+}
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_for_parent_context_variables_template.js b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_for_parent_context_variables_template.js
new file mode 100644
index 0000000000..a5095338d0
--- /dev/null
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_for_parent_context_variables_template.js
@@ -0,0 +1,41 @@
+function MyComponent_div_0_span_1_Template(rf, ctx) {
+ if (rf & 1) {
+ $i0$.ɵɵelementStart(0, "span");
+ $i0$.ɵɵtext(1);
+ $i0$.ɵɵelementEnd();
+ }
+ if (rf & 2) {
+ const $div$ = $i0$.ɵɵnextContext();
+ const $i$ = $div$.index;
+ const $item$ = $div$.$implicit;
+ $r3$.ɵɵadvance(1);
+ $i0$.ɵɵtextInterpolate2(" ", $i$, " - ", $item$, " ");
+ }
+}
+
+function MyComponent_div_0_Template(rf, ctx) {
+ if (rf & 1) {
+ $i0$.ɵɵelementStart(0, "div");
+ $i0$.ɵɵtemplate(1, MyComponent_div_0_span_1_Template, 2, 2, "span", 1);
+ $i0$.ɵɵelementEnd();
+ }
+ if (rf & 2) {
+ const $app$ = $i0$.ɵɵnextContext();
+ $r3$.ɵɵadvance(1);
+ $i0$.ɵɵproperty("ngIf", $app$.showing);
+ }
+}
+
+…
+consts: [
+ [__AttributeMarker.Template__, "ngFor", "ngForOf"],
+ [__AttributeMarker.Template__, "ngIf"]
+],
+template:function MyComponent_Template(rf, ctx){
+ if (rf & 1) {
+ $i0$.ɵɵtemplate(0, MyComponent_div_0_Template, 2, 1, "div", 0);
+ }
+ if (rf & 2) {
+ $i0$.ɵɵproperty("ngForOf", ctx.items);
+ }
+}
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_template.ts b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_template.ts
new file mode 100644
index 0000000000..652e8aedf8
--- /dev/null
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_template.ts
@@ -0,0 +1,15 @@
+import {Component, NgModule} from '@angular/core';
+
+@Component({
+ selector: 'my-component',
+ template: `
+
+ some-content
+ `
+})
+export class MyComponent {
+}
+
+@NgModule({declarations: [MyComponent]})
+export class MyModule {
+}
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_template_interpolated_prop.ts b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_template_interpolated_prop.ts
new file mode 100644
index 0000000000..d412b5a32b
--- /dev/null
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_template_interpolated_prop.ts
@@ -0,0 +1,14 @@
+import {Component, Directive, Input} from '@angular/core';
+
+@Directive({selector: '[dir]'})
+class WithInput {
+ @Input() dir: string = '';
+}
+
+@Component({
+ selector: 'my-app',
+ template: '',
+})
+export class TestComp {
+ message = 'Hello';
+}
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_template_interpolated_prop_template.js b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_template_interpolated_prop_template.js
new file mode 100644
index 0000000000..7c4b8072b7
--- /dev/null
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_template_interpolated_prop_template.js
@@ -0,0 +1,9 @@
+consts: [[__AttributeMarker.Bindings__, "dir"]],
+template: function TestComp_Template(rf, ctx) {
+ if (rf & 1) {
+ $i0$.ɵɵtemplate(0, $TestComp_ng_template_0_Template$, 0, 0, "ng-template", 0);
+ }
+ if (rf & 2) {
+ $i0$.ɵɵpropertyInterpolate("dir", ctx.message);
+ }
+}
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_template_interpolated_prop_with_structural_directive.ts b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_template_interpolated_prop_with_structural_directive.ts
new file mode 100644
index 0000000000..07136bd62f
--- /dev/null
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_template_interpolated_prop_with_structural_directive.ts
@@ -0,0 +1,14 @@
+import {Component, Directive, Input} from '@angular/core';
+
+@Directive({selector: '[dir]'})
+class WithInput {
+ @Input() dir: string = '';
+}
+
+@Component({
+ selector: 'my-app',
+ template: '',
+})
+export class TestComp {
+ message = 'Hello';
+}
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_template_interpolated_prop_with_structural_directive_inner_template.js b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_template_interpolated_prop_with_structural_directive_inner_template.js
new file mode 100644
index 0000000000..71f23817e2
--- /dev/null
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_template_interpolated_prop_with_structural_directive_inner_template.js
@@ -0,0 +1,9 @@
+function $TestComp_0_Template$(rf, ctx) {
+ if (rf & 1) {
+ $i0$.ɵɵtemplate(0, $TestComp_0_ng_template_0_Template$, 0, 0, "ng-template", 1);
+ }
+ if (rf & 2) {
+ const $ctx_r0$ = i0.ɵɵnextContext();
+ $i0$.ɵɵpropertyInterpolate("dir", $ctx_r0$.message);
+ }
+}
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_template_interpolated_prop_with_structural_directive_outer_template.js b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_template_interpolated_prop_with_structural_directive_outer_template.js
new file mode 100644
index 0000000000..52659e1728
--- /dev/null
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_template_interpolated_prop_with_structural_directive_outer_template.js
@@ -0,0 +1,9 @@
+consts: [[4, "ngIf"], [3, "dir"]],
+template: function TestComp_Template(rf, ctx) {
+ if (rf & 1) {
+ $i0$.ɵɵtemplate(0, $TestComp_0_Template$, 1, 1, undefined, 0);
+ }
+ if (rf & 2) {
+ $i0$.ɵɵproperty("ngIf", true);
+ }
+},
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_template_local_ref.ts b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_template_local_ref.ts
new file mode 100644
index 0000000000..2e1f814e12
--- /dev/null
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_template_local_ref.ts
@@ -0,0 +1,12 @@
+import {Component, NgModule} from '@angular/core';
+
+@Component({
+ selector: 'my-component',
+ template: 'some-content',
+})
+export class MyComponent {
+}
+
+@NgModule({declarations: [MyComponent]})
+export class MyModule {
+}
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_template_local_ref_template.js b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_template_local_ref_template.js
new file mode 100644
index 0000000000..643bb6eb7c
--- /dev/null
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_template_local_ref_template.js
@@ -0,0 +1,13 @@
+function MyComponent_ng_template_0_Template(rf, ctx) {
+ if (rf & 1) {
+ $i0$.ɵɵtext(0, "some-content");
+ }
+}
+
+…
+consts: [["foo", ""]],
+template: function MyComponent_Template(rf, ctx) {
+ if (rf & 1) {
+ $i0$.ɵɵtemplate(0, MyComponent_ng_template_0_Template, 1, 0, "ng-template", null, 0, $i0$.ɵɵtemplateRefExtractor);
+ }
+}
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_template_output.ts b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_template_output.ts
new file mode 100644
index 0000000000..cb2d98ff17
--- /dev/null
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_template_output.ts
@@ -0,0 +1,12 @@
+import {Component, NgModule} from '@angular/core';
+
+@Component({
+ selector: 'my-component',
+ template: '',
+})
+export class MyComponent {
+}
+
+@NgModule({declarations: [MyComponent]})
+export class MyModule {
+}
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_template_output_template.js b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_template_output_template.js
new file mode 100644
index 0000000000..a000e22567
--- /dev/null
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_template_output_template.js
@@ -0,0 +1,11 @@
+function MyComponent_ng_template_0_Template(rf, ctx) { }
+
+…
+
+consts: [[__AttributeMarker.Bindings__, "outDirective"]],
+template: function MyComponent_Template(rf, ctx) {
+ if (rf & 1) {
+ $i0$.ɵɵtemplate(0, MyComponent_ng_template_0_Template, 0, 0, "ng-template", 0);
+ $i0$.ɵɵlistener("outDirective", function MyComponent_Template_ng_template_outDirective_0_listener($event) { return $event.doSth(); });
+ }
+}
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_template_template.js b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_template_template.js
new file mode 100644
index 0000000000..f352ea298d
--- /dev/null
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/ng_template_template.js
@@ -0,0 +1,17 @@
+function MyComponent_ng_template_0_Template(rf, ctx) {
+ if (rf & 1) {
+ $i0$.ɵɵtext(0, " some-content ");
+ }
+}
+
+…
+
+consts: [["attr", "l", __AttributeMarker.Bindings__, "boundAttr"]],
+template: function MyComponent_Template(rf, ctx) {
+ if (rf & 1) {
+ $i0$.ɵɵtemplate(0, MyComponent_ng_template_0_Template, 1, 0, "ng-template", 0);
+ }
+ if (rf & 2) {
+ $i0$.ɵɵproperty("boundAttr", ctx.b);
+ }
+}
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/template_binding_pipe.ts b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/template_binding_pipe.ts
new file mode 100644
index 0000000000..d67529295a
--- /dev/null
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/template_binding_pipe.ts
@@ -0,0 +1,12 @@
+import {Component, NgModule} from '@angular/core';
+
+@Component({
+ selector: 'my-component',
+ template: ``,
+})
+export class MyComponent {
+}
+
+@NgModule({declarations: [MyComponent]})
+export class MyModule {
+}
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/template_binding_pipe_template.js b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/template_binding_pipe_template.js
new file mode 100644
index 0000000000..00646435a3
--- /dev/null
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/template_binding_pipe_template.js
@@ -0,0 +1,16 @@
+function MyComponent_div_0_Template(rf, ctx) {
+ if (rf & 1) {
+ $i0$.ɵɵelement(0, "div");
+ }
+}
+
+…
+consts: [[__AttributeMarker.Template__, "ngIf"]],
+template: function MyComponent_Template(rf, ctx) {
+ if (rf & 1) {
+ $i0$.ɵɵtemplate(0, MyComponent_div_0_Template, 1, 0, "div", 0);
+ $i0$.ɵɵpipe(1, "pipe");
+ } if (rf & 2) {
+ $i0$.ɵɵproperty("ngIf", $i0$.ɵɵpipeBind1(1, 1, ctx.val));
+ }
+}
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/template_context_skip.ts b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/template_context_skip.ts
new file mode 100644
index 0000000000..a351704bf2
--- /dev/null
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/template_context_skip.ts
@@ -0,0 +1,19 @@
+import {Component, NgModule} from '@angular/core';
+
+@Component({
+ selector: 'my-component',
+ template: `
+
+
+
+ {{ middle.value }} - {{ name }}
+
+
+
`
+})
+export class MyComponent {
+}
+
+@NgModule({declarations: [MyComponent]})
+export class MyModule {
+}
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/template_context_skip_template.js b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/template_context_skip_template.js
new file mode 100644
index 0000000000..289254d6cf
--- /dev/null
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/template_context_skip_template.js
@@ -0,0 +1,49 @@
+function MyComponent_div_0_div_1_div_1_Template(rf, ctx) {
+ if (rf & 1) {
+ $i0$.ɵɵelementStart(0, "div");
+ $i0$.ɵɵtext(1);
+ $i0$.ɵɵelementEnd();
+ }
+ if (rf & 2) {
+ const $middle$ = $i0$.ɵɵnextContext().$implicit;
+ const $myComp$ = $i0$.ɵɵnextContext(2);
+ $r3$.ɵɵadvance(1);
+ $i0$.ɵɵtextInterpolate2(" ", $middle$.value, " - ", $myComp$.name, " ");
+ }
+}
+
+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", 0);
+ $i0$.ɵɵelementEnd();
+ }
+ if (rf & 2) {
+ const $middle$ = ctx.$implicit;
+ $r3$.ɵɵadvance(1);
+ $i0$.ɵɵproperty("ngForOf", $middle$.items);
+ }
+}
+
+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", 0);
+ $i0$.ɵɵelementEnd();
+ }
+ if (rf & 2) {
+ const $outer$ = ctx.$implicit;
+ $r3$.ɵɵadvance(1);
+ $i0$.ɵɵproperty("ngForOf", $outer$.items);
+ }
+}
+…
+consts: [[__AttributeMarker.Template__, "ngFor", "ngForOf"]],
+template: function MyComponent_Template(rf, ctx){
+ if (rf & 1) {
+ $i0$.ɵɵtemplate(0, MyComponent_div_0_Template, 2, 1, "div", 0);
+ }
+ if (rf & 2) {
+ $i0$.ɵɵproperty("ngForOf", ctx.items);
+ }
+}
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/unique_listener_function_names.js b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/unique_listener_function_names.js
new file mode 100644
index 0000000000..df0dbb1fe7
--- /dev/null
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/unique_listener_function_names.js
@@ -0,0 +1,2 @@
+…
+// NOTE: the assertions for this test happen through `verifyUniqueFunctions`.
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/unique_listener_function_names.ts b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/unique_listener_function_names.ts
new file mode 100644
index 0000000000..65209e15a7
--- /dev/null
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/unique_listener_function_names.ts
@@ -0,0 +1,21 @@
+import {Component, NgModule} from '@angular/core';
+
+@Component({
+ selector: 'my-component',
+ template: `
+
+
{{ item }}
+
{{ item }}
+
+
+ `,
+})
+export class MyComponent {
+ items = [4, 2];
+}
+
+@NgModule({declarations: [MyComponent]})
+export class MyModule {
+}
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/unique_template_function_names.js b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/unique_template_function_names.js
new file mode 100644
index 0000000000..df0dbb1fe7
--- /dev/null
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/unique_template_function_names.js
@@ -0,0 +1,2 @@
+…
+// NOTE: the assertions for this test happen through `verifyUniqueFunctions`.
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/unique_template_function_names.ts b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/unique_template_function_names.ts
new file mode 100644
index 0000000000..7971367fa7
--- /dev/null
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/unique_template_function_names.ts
@@ -0,0 +1,51 @@
+import {Component, NgModule} from '@angular/core';
+
+@Component({
+ selector: 'a-component',
+ template: `
+
+
less than 10
+
less than 10
+
+
+ `,
+})
+export class AComponent {
+ items = [4, 2];
+}
+
+@NgModule({declarations: [AComponent]})
+export class AModule {
+}
+
+@Component({
+ selector: 'b-component',
+ template: `
+
+
+ less than 10
+ less than 10
+
+
+ less than 10
+
+
+
+ `,
+})
+export class BComponent {
+ items = [
+ {subitems: [1, 3]},
+ {subitems: [3, 7]},
+ ];
+}
+
+@NgModule({declarations: [BComponent]})
+export class BModule {
+}
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/unique_template_function_names_ng_content.js b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/unique_template_function_names_ng_content.js
new file mode 100644
index 0000000000..df0dbb1fe7
--- /dev/null
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/unique_template_function_names_ng_content.js
@@ -0,0 +1,2 @@
+…
+// NOTE: the assertions for this test happen through `verifyUniqueFunctions`.
diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/unique_template_function_names_ng_content.ts b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/unique_template_function_names_ng_content.ts
new file mode 100644
index 0000000000..4d5c55c5b1
--- /dev/null
+++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_template/unique_template_function_names_ng_content.ts
@@ -0,0 +1,25 @@
+import {Component, NgModule} from '@angular/core';
+
+@Component({
+ selector: 'a-component',
+ template: `
+
+ `,
+})
+export class AComponent {
+ show = true;
+}
+
+@Component({
+ selector: 'b-component',
+ template: `
+
+ `,
+})
+export class BComponent {
+ show = true;
+}
+
+@NgModule({declarations: [AComponent, BComponent]})
+export class AModule {
+}
diff --git a/packages/compiler-cli/test/compliance/test_helpers/check_expectations.ts b/packages/compiler-cli/test/compliance/test_helpers/check_expectations.ts
index 9d49645775..80e576c155 100644
--- a/packages/compiler-cli/test/compliance/test_helpers/check_expectations.ts
+++ b/packages/compiler-cli/test/compliance/test_helpers/check_expectations.ts
@@ -11,6 +11,7 @@ import {getBuildOutputDirectory, getRootDirectory} from './compile_test';
import {verifyUniqueFactory} from './di_checks';
import {expectEmit} from './expect_emit';
import {replaceMacros} from './expected_file_macros';
+import {verifyUniqueFunctions} from './function_checks';
import {ExpectedFile, ExtraCheck} from './get_compliance_tests';
import {verifyPlaceholdersIntegrity, verifyUniqueConsts} from './i18n_checks';
@@ -19,6 +20,7 @@ const EXTRA_CHECK_FUNCTIONS: Record = {
verifyPlaceholdersIntegrity,
verifyUniqueConsts,
verifyUniqueFactory,
+ verifyUniqueFunctions,
};
/**
diff --git a/packages/compiler-cli/test/compliance/test_helpers/function_checks.ts b/packages/compiler-cli/test/compliance/test_helpers/function_checks.ts
new file mode 100644
index 0000000000..6ed3b39579
--- /dev/null
+++ b/packages/compiler-cli/test/compliance/test_helpers/function_checks.ts
@@ -0,0 +1,29 @@
+/**
+ * @license
+ * Copyright Google LLC All Rights Reserved.
+ *
+ * Use of this source code is governed by an MIT-style license that can be
+ * found in the LICENSE file at https://angular.io/license
+ */
+
+/**
+ * Verify that all functions in the output have a unique name.
+ * @param output Compiler output.
+ * @param functionNamePattern Only match function whose names match this pattern.
+ * Will be converted into a regular expression.
+ * @param expectedCount Expected number of functions.
+ */
+export function verifyUniqueFunctions(
+ output: string, functionNamePattern?: string, expectedCount?: number): boolean {
+ const pattern = functionNamePattern ? new RegExp(functionNamePattern) : null;
+ const allTemplateFunctionsNames = (output.match(/function ([^\s(]+)/g) || [])
+ .map(match => match.slice(9))
+ .filter(name => !pattern || pattern.test(name));
+ const uniqueTemplateFunctionNames = new Set(allTemplateFunctionsNames);
+ const lengthMatches = allTemplateFunctionsNames.length === uniqueTemplateFunctionNames.size;
+ const expectedCountMatches =
+ (expectedCount == null ? allTemplateFunctionsNames.length > 0 :
+ allTemplateFunctionsNames.length === expectedCount);
+ return lengthMatches && expectedCountMatches &&
+ allTemplateFunctionsNames.every(name => uniqueTemplateFunctionNames.has(name));
+}