diff --git a/packages/compiler-cli/test/ngc_spec.ts b/packages/compiler-cli/test/ngc_spec.ts index 1a1d9984f2..eb80136e45 100644 --- a/packages/compiler-cli/test/ngc_spec.ts +++ b/packages/compiler-cli/test/ngc_spec.ts @@ -898,12 +898,12 @@ describe('ngc transformer command-line', () => { export * from './util'; - // Note: the lamda will be lowered into an exported expression + // Note: the lambda will be lowered into an exported expression @NgModule({providers: [{provide: 'aToken', useValue: () => 2}]}) export class MyModule {} `); write('util.ts', ` - // Note: The lamda will be lowered into an exported expression + // Note: The lambda will be lowered into an exported expression const x = () => 2; export const y = x; @@ -1144,7 +1144,7 @@ describe('ngc transformer command-line', () => { shouldExist('app/main.js'); }); - it('shoud be able to compile libraries with summaries and flat modules', () => { + it('should be able to compile libraries with summaries and flat modules', () => { writeFiles(); compile(); @@ -1466,7 +1466,7 @@ describe('ngc transformer command-line', () => { `); })); - it('should recomiple when the html file changes', + it('should recompile when the html file changes', expectRecompile(() => { write('greet.html', '

Hello {{name}} again!

'); })); it('should recompile when the css file changes', diff --git a/packages/compiler/src/render3/r3_identifiers.ts b/packages/compiler/src/render3/r3_identifiers.ts index 8c80c69c71..bdc4e71188 100644 --- a/packages/compiler/src/render3/r3_identifiers.ts +++ b/packages/compiler/src/render3/r3_identifiers.ts @@ -62,7 +62,6 @@ export class Identifiers { static bind6: o.ExternalReference = {name: 'ɵb6', moduleName: CORE}; static bind7: o.ExternalReference = {name: 'ɵb7', moduleName: CORE}; static bind8: o.ExternalReference = {name: 'ɵb8', moduleName: CORE}; - static bind9: o.ExternalReference = {name: 'ɵb9', moduleName: CORE}; static bindV: o.ExternalReference = {name: 'ɵbV', moduleName: CORE}; static memory: o.ExternalReference = {name: 'ɵm', moduleName: CORE}; diff --git a/packages/compiler/src/render3/r3_view_compiler.ts b/packages/compiler/src/render3/r3_view_compiler.ts index 63112d2c0a..ea3ff2e8a3 100644 --- a/packages/compiler/src/render3/r3_view_compiler.ts +++ b/packages/compiler/src/render3/r3_view_compiler.ts @@ -157,8 +157,6 @@ function interpolate(args: o.Expression[]): o.Expression { return o.importExpr(R3.bind7).callFn(args); case 17: return o.importExpr(R3.bind8).callFn(args); - case 19: - return o.importExpr(R3.bind9).callFn(args); } (args.length > 19 && args.length % 2 == 1) || error(`Invalid interpolation argument length ${args.length}`); diff --git a/packages/core/src/core_render3_private_export.ts b/packages/core/src/core_render3_private_export.ts index eedf323afc..a1306fec04 100644 --- a/packages/core/src/core_render3_private_export.ts +++ b/packages/core/src/core_render3_private_export.ts @@ -11,6 +11,7 @@ export { defineComponent as ɵdefineComponent, detectChanges as ɵdetectChanges, renderComponent as ɵrenderComponent, + ComponentType as ɵComponentType, C as ɵC, E as ɵE, L as ɵL, @@ -18,6 +19,14 @@ export { V as ɵV, b as ɵb, b1 as ɵb1, + b2 as ɵb2, + b3 as ɵb3, + b4 as ɵb4, + b5 as ɵb5, + b6 as ɵb6, + b7 as ɵb7, + b8 as ɵb8, + bV as ɵbV, cR as ɵcR, cr as ɵcr, e as ɵe, diff --git a/packages/core/test/render3/compiler_canonical_spec.ts b/packages/core/test/render3/compiler_canonical_spec.ts index f6a8fdad3a..37ef050769 100644 --- a/packages/core/test/render3/compiler_canonical_spec.ts +++ b/packages/core/test/render3/compiler_canonical_spec.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {Component, Directive, Injectable, NgModule, Optional, TemplateRef, Type} from '../../src/core'; +import {Component, Directive, Injectable, Input, NgModule, Optional, SimpleChanges, TemplateRef, Type, ViewContainerRef} from '../../src/core'; import * as r3 from '../../src/render3/index'; import {containerEl, renderComponent, requestAnimationFrame, toHtml} from './render_util'; @@ -193,6 +193,193 @@ describe('compiler specification', () => { }); }); + describe('template variables', () => { + + interface ForOfContext { + $implicit: any; + index: number; + even: boolean; + odd: boolean; + } + + @Directive({selector: '[forOf]'}) + class ForOfDirective { + private previous: any[]; + + constructor(private view: ViewContainerRef, private template: TemplateRef) {} + + @Input() forOf: any[]; + + ngOnChanges(simpleChanges: SimpleChanges) { + if ('forOf' in simpleChanges) { + this.update(); + } + } + + ngDoCheck(): void { + const previous = this.previous; + const current = this.forOf; + if (!previous || previous.length != current.length || + previous.some((value: any, index: number) => current[index] !== previous[index])) { + this.update(); + } + } + + private update() { + // TODO(chuckj): Not implemented yet + // this.view.clear(); + if (this.forOf) { + const current = this.forOf; + for (let i = 0; i < current.length; i++) { + const context = {$implicit: current[i], index: i, even: i % 2 == 0, odd: i % 2 == 1}; + // TODO(chuckj): Not implemented yet + // this.view.createEmbeddedView(this.template, context); + } + this.previous = [...this.forOf]; + } + } + + // NORMATIVE + static ngDirectiveDef = r3.defineDirective({ + factory: function ForOfDirective_Factory() { + return new ForOfDirective(r3.injectViewContainerRef(), r3.injectTemplateRef()); + }, + // TODO(chuckj): Enable when ngForOf enabling lands. + // features: [NgOnChangesFeature(NgForOf)], + refresh: function ForOfDirective_Refresh(directiveIndex: number, elementIndex: number) { + r3.m(directiveIndex).ngDoCheck(); + }, + inputs: {forOf: 'forOf'} + }); + // /NORMATIVE + } + + it('should support a let variable and reference', () => { + interface Item { + name: string; + } + + const c1_dirs = [ForOfDirective]; + + @Component({ + selector: 'my-component', + template: `` + }) + class MyComponent { + items = [{name: 'one'}, {name: 'two'}]; + + // NORMATIVE + static ngComponentDef = r3.defineComponent({ + tag: 'my-component', + factory: function MyComponent_Factory() { return new MyComponent(); }, + template: function MyComponentTemplate(ctx: MyComponent, cm: boolean) { + if (cm) { + r3.E(0, 'ul'); + r3.C(1, c1_dirs, MyComponent_ForOfDirective_Template_1); + r3.e(); + } + r3.p(1, 'forOf', r3.b(ctx.items)); + r3.cR(1); + ForOfDirective.ngDirectiveDef.r(2, 1); + r3.cr(); + + function MyComponent_ForOfDirective_Template_1(ctx1: any, cm: boolean) { + if (cm) { + r3.E(0, 'li'); + r3.T(1); + r3.e(); + } + const l0_item = ctx1.$implicit; + r3.t(1, r3.b1('', l0_item.name, '')); + } + } + }); + // /NORMATIVE + } + + // TODO(chuckj): update when the changes to enable ngForOf lands. + expect(renderComp(MyComponent)).toEqual(''); + }); + + it('should support accessing parent template variables', () => { + interface Info { + description: string; + } + interface Item { + name: string; + infos: Info[]; + } + + const c1_dirs = [ForOfDirective]; + + @Component({ + selector: 'my-component', + template: ` +