feat(ivy): render flags support in host bindings function (FW-649) (#27204)

PR Close #27204
This commit is contained in:
Andrew Kushnir
2018-11-20 15:20:19 -08:00
committed by Misko Hevery
parent bf71b107b3
commit dc300c5c41
21 changed files with 334 additions and 248 deletions

View File

@ -145,8 +145,10 @@ describe('compiler compliance: bindings', () => {
type: HostBindingDir,
selectors: [["", "hostBindingDir", ""]],
factory: function HostBindingDir_Factory(t) { return new (t || HostBindingDir)(); },
hostBindings: function HostBindingDir_HostBindings(dirIndex, elIndex) {
$r3$.ɵelementProperty(elIndex, "id", $r3$.ɵbind($r3$.ɵload(dirIndex).dirId));
hostBindings: function HostBindingDir_HostBindings(rf, ctx, elIndex) {
if (rf & 2) {
$r3$.ɵelementProperty(elIndex, "id", $r3$.ɵbind(ctx.dirId));
}
},
hostVars: 1
});
@ -188,8 +190,10 @@ describe('compiler compliance: bindings', () => {
type: HostBindingComp,
selectors: [["host-binding-comp"]],
factory: function HostBindingComp_Factory(t) { return new (t || HostBindingComp)(); },
hostBindings: function HostBindingComp_HostBindings(dirIndex, elIndex) {
$r3$.ɵelementProperty(elIndex, "id", $r3$.ɵbind($r3$.ɵpureFunction1(1, $ff$, $r3$.ɵload(dirIndex).id)));
hostBindings: function HostBindingComp_HostBindings(rf, ctx, elIndex) {
if (rf & 2) {
$r3$.ɵelementProperty(elIndex, "id", $r3$.ɵbind($r3$.ɵpureFunction1(1, $ff$, ctx.id)));
}
},
hostVars: 3,
consts: 0,
@ -232,8 +236,10 @@ describe('compiler compliance: bindings', () => {
type: HostAttributeDir,
selectors: [["", "hostAttributeDir", ""]],
factory: function HostAttributeDir_Factory(t) { return new (t || HostAttributeDir)(); },
hostBindings: function HostAttributeDir_HostBindings(dirIndex, elIndex) {
$r3$.ɵelementAttribute(elIndex, "required", $r3$.ɵbind($r3$.ɵload(dirIndex).required));
hostBindings: function HostAttributeDir_HostBindings(rf, ctx, elIndex) {
if (rf & 2) {
$r3$.ɵelementAttribute(elIndex, "required", $r3$.ɵbind(ctx.required));
}
},
hostVars: 1
});

View File

@ -771,12 +771,16 @@ describe('compiler compliance: styling', () => {
const _c0 = ["foo", "baz", ${InitialStylingFlags.VALUES_MODE}, "foo", true, "baz", true];
const _c1 = ["width", "height", "color", ${InitialStylingFlags.VALUES_MODE}, "width", "200px", "height", "500px"];
hostBindings: function MyComponent_HostBindings(dirIndex, elIndex) {
$r3$.ɵelementStyling(_c0, _c1, $r3$.ɵdefaultStyleSanitizer, dirIndex);
$r3$.ɵelementStylingMap(elIndex, $r3$.ɵload(dirIndex).myClass, $r3$.ɵload(dirIndex).myStyle, dirIndex);
$r3$.ɵelementStyleProp(elIndex, 2, $r3$.ɵload(dirIndex).myColorProp, null, dirIndex);
$r3$.ɵelementClassProp(elIndex, 0, $r3$.ɵload(dirIndex).myFooClass, dirIndex);
$r3$.ɵelementStylingApply(elIndex, dirIndex);
hostBindings: function MyComponent_HostBindings(rf, ctx, elIndex) {
if (rf & 1) {
$r3$.ɵelementStyling(_c0, _c1, $r3$.ɵdefaultStyleSanitizer, ctx);
}
if (rf & 2) {
$r3$.ɵelementStylingMap(elIndex, ctx.myClass, ctx.myStyle, ctx);
$r3$.ɵelementStyleProp(elIndex, 2, ctx.myColorProp, null, ctx);
$r3$.ɵelementClassProp(elIndex, 0, ctx.myFooClass, ctx);
$r3$.ɵelementStylingApply(elIndex, ctx);
}
}
`;
@ -825,14 +829,18 @@ describe('compiler compliance: styling', () => {
const _c0 = ["bar", "foo"];
const _c1 = ["height", "width"];
hostBindings: function MyComponent_HostBindings(dirIndex, elIndex) {
$r3$.ɵelementStyling(_c0, _c1, $r3$.ɵdefaultStyleSanitizer, dirIndex);
$r3$.ɵelementStylingMap(elIndex, $r3$.ɵload(dirIndex).myClasses, $r3$.ɵload(dirIndex).myStyle, dirIndex);
$r3$.ɵelementStyleProp(elIndex, 0, $r3$.ɵload(dirIndex).myHeightProp, "pt", dirIndex);
$r3$.ɵelementStyleProp(elIndex, 1, $r3$.ɵload(dirIndex).myWidthProp, null, dirIndex);
$r3$.ɵelementClassProp(elIndex, 0, $r3$.ɵload(dirIndex).myBarClass, dirIndex);
$r3$.ɵelementClassProp(elIndex, 1, $r3$.ɵload(dirIndex).myFooClass, dirIndex);
$r3$.ɵelementStylingApply(elIndex, dirIndex);
hostBindings: function MyComponent_HostBindings(rf, ctx, elIndex) {
if (rf & 1) {
$r3$.ɵelementStyling(_c0, _c1, $r3$.ɵdefaultStyleSanitizer, ctx);
}
if (rf & 2) {
$r3$.ɵelementStylingMap(elIndex, ctx.myClasses, ctx.myStyle, ctx);
$r3$.ɵelementStyleProp(elIndex, 0, ctx.myHeightProp, "pt", ctx);
$r3$.ɵelementStyleProp(elIndex, 1, ctx.myWidthProp, null, ctx);
$r3$.ɵelementClassProp(elIndex, 0, ctx.myBarClass, ctx);
$r3$.ɵelementClassProp(elIndex, 1, ctx.myFooClass, ctx);
$r3$.ɵelementStylingApply(elIndex, ctx);
}
}
`;
@ -886,18 +894,26 @@ describe('compiler compliance: styling', () => {
const _c2 = ["bar"];
const _c3 = ["height"];
function WidthDirective_HostBindings(dirIndex, elIndex) {
$r3$.ɵelementStyling(_c0, _c1, null, dirIndex);
$r3$.ɵelementStyleProp(elIndex, 0, $r3$.ɵload(dirIndex).myWidth, null, dirIndex);
$r3$.ɵelementClassProp(elIndex, 0, $r3$.ɵload(dirIndex).myFooClass, dirIndex);
$r3$.ɵelementStylingApply(elIndex, dirIndex);
function WidthDirective_HostBindings(rf, ctx, elIndex) {
if (rf & 1) {
$r3$.ɵelementStyling(_c0, _c1, null, ctx);
}
if (rf & 2) {
$r3$.ɵelementStyleProp(elIndex, 0, ctx.myWidth, null, ctx);
$r3$.ɵelementClassProp(elIndex, 0, ctx.myFooClass, ctx);
$r3$.ɵelementStylingApply(elIndex, ctx);
}
}
function HeightDirective_HostBindings(dirIndex, elIndex) {
$r3$.ɵelementStyling(_c2, _c3, null, dirIndex);
$r3$.ɵelementStyleProp(elIndex, 0, $r3$.ɵload(dirIndex).myHeight, null, dirIndex);
$r3$.ɵelementClassProp(elIndex, 0, $r3$.ɵload(dirIndex).myBarClass, dirIndex);
$r3$.ɵelementStylingApply(elIndex, dirIndex);
function HeightDirective_HostBindings(rf, ctx, elIndex) {
if (rf & 1) {
$r3$.ɵelementStyling(_c2, _c3, null, ctx);
}
if (rf & 2) {
$r3$.ɵelementStyleProp(elIndex, 0, ctx.myHeight, null, ctx);
$r3$.ɵelementClassProp(elIndex, 0, ctx.myBarClass, ctx);
$r3$.ɵelementStylingApply(elIndex, ctx);
}
}
`;

View File

@ -8,6 +8,8 @@
import {NgtscTestEnvironment} from './env';
const trim = (input: string): string => input.replace(/\s+/g, ' ').trim();
describe('ngtsc behavioral tests', () => {
if (!NgtscTestEnvironment.supported) {
// These tests should be excluded from the non-Bazel build.
@ -449,6 +451,37 @@ describe('ngtsc behavioral tests', () => {
expect(jsContents).toContain(`i0.ɵquery(null, ViewContainerRef, true)`);
});
it('should generate host listeners for components', () => {
env.tsconfig();
env.write(`test.ts`, `
import {Component, HostListener} from '@angular/core';
@Component({
selector: 'test',
template: 'Test'
})
class FooCmp {
@HostListener('document:click', ['$event.target'])
onClick(eventTarget: HTMLElement): void {}
@HostListener('window:scroll')
onScroll(event: any): void {}
}
`);
env.driveMain();
const jsContents = env.getContents('test.js');
const hostBindingsFn = `
hostBindings: function FooCmp_HostBindings(rf, ctx, elIndex) {
if (rf & 1) {
i0.ɵlistener("click", function FooCmp_click_HostBindingHandler($event) { return ctx.onClick($event.target); });
i0.ɵlistener("scroll", function FooCmp_scroll_HostBindingHandler($event) { return ctx.onScroll(); });
}
}
`;
expect(trim(jsContents)).toContain(trim(hostBindingsFn));
});
it('should generate host bindings for directives', () => {
env.tsconfig();
env.write(`test.ts`, `
@ -476,39 +509,33 @@ describe('ngtsc behavioral tests', () => {
env.driveMain();
const jsContents = env.getContents('test.js');
expect(jsContents)
.toContain(`i0.ɵelementAttribute(elIndex, "hello", i0.ɵbind(i0.ɵload(dirIndex).foo));`);
expect(jsContents)
.toContain(`i0.ɵelementProperty(elIndex, "prop", i0.ɵbind(i0.ɵload(dirIndex).bar));`);
expect(jsContents)
.toContain('i0.ɵelementClassProp(elIndex, 0, i0.ɵload(dirIndex).someClass, dirIndex)');
const factoryDef = `
factory: function FooCmp_Factory(t) {
var f = new (t || FooCmp)();
i0.ɵlistener("click", function FooCmp_click_HostBindingHandler($event) {
return f.onClick($event);
});
i0.ɵlistener("change", function FooCmp_change_HostBindingHandler($event) {
return f.onChange(f.arg1, f.arg2, f.arg3);
});
return f;
const hostBindingsFn = `
hostBindings: function FooCmp_HostBindings(rf, ctx, elIndex) {
if (rf & 1) {
i0.ɵlistener("click", function FooCmp_click_HostBindingHandler($event) { return ctx.onClick($event); });
i0.ɵlistener("change", function FooCmp_change_HostBindingHandler($event) { return ctx.onChange(ctx.arg1, ctx.arg2, ctx.arg3); });
i0.ɵelementStyling(_c0, null, null, ctx);
}
if (rf & 2) {
i0.ɵelementAttribute(elIndex, "hello", i0.ɵbind(ctx.foo));
i0.ɵelementProperty(elIndex, "prop", i0.ɵbind(ctx.bar));
i0.ɵelementClassProp(elIndex, 0, ctx.someClass, ctx);
i0.ɵelementStylingApply(elIndex, ctx);
}
}
`;
expect(jsContents).toContain(factoryDef.replace(/\s+/g, ' ').trim());
expect(trim(jsContents)).toContain(trim(hostBindingsFn));
});
it('should generate host listeners for directives with base factories', () => {
it('should generate host listeners for directives within hostBindings section', () => {
env.tsconfig();
env.write(`test.ts`, `
import {Directive, HostListener} from '@angular/core';
class Base {}
@Directive({
selector: '[test]',
})
class Dir extends Base {
class Dir {
@HostListener('change', ['arg'])
onChange(event: any, arg: any): void {}
}
@ -516,17 +543,14 @@ describe('ngtsc behavioral tests', () => {
env.driveMain();
const jsContents = env.getContents('test.js');
const factoryDef = `
factory: function Dir_Factory(t) {
var f = ɵDir_BaseFactory((t || Dir));
i0.ɵlistener("change", function Dir_change_HostBindingHandler($event) {
return f.onChange(f.arg);
});
return f;
const hostBindingsFn = `
hostBindings: function Dir_HostBindings(rf, ctx, elIndex) {
if (rf & 1) {
i0.ɵlistener("change", function Dir_change_HostBindingHandler($event) { return ctx.onChange(ctx.arg); });
}
}
`;
expect(jsContents).toContain(factoryDef.replace(/\s+/g, ' ').trim());
expect(jsContents).toContain('var ɵDir_BaseFactory = i0.ɵgetInheritedFactory(Dir)');
expect(trim(jsContents)).toContain(trim(hostBindingsFn));
});
it('should correctly recognize local symbols', () => {