fix(ivy): call `hostBindings` function with proper element index (#27694)
We invoked `hostBindings` function in Create and Update modes with different element index due to the fact that we did not subtract HEADER_OFFSET from the index before passing it to `hostBindings` function in Create mode. Now we subtract HEADER_OFFSET value before invoking `hostBindings`, which makes Ceate and Update calls consistent. PR Close #27694
This commit is contained in:
parent
4c1cd1bb78
commit
9bfe42840b
|
@ -198,7 +198,7 @@ export function createRootComponent<T>(
|
|||
if (tView.firstTemplatePass && componentDef.hostBindings) {
|
||||
const rootTNode = getPreviousOrParentTNode();
|
||||
setCurrentDirectiveDef(componentDef);
|
||||
componentDef.hostBindings(RenderFlags.Create, component, rootTNode.index);
|
||||
componentDef.hostBindings(RenderFlags.Create, component, rootTNode.index - HEADER_OFFSET);
|
||||
setCurrentDirectiveDef(null);
|
||||
}
|
||||
|
||||
|
|
|
@ -1541,7 +1541,7 @@ function invokeDirectivesHostBindings(tView: TView, viewData: LView, tNode: TNod
|
|||
if (def.hostBindings) {
|
||||
const previousExpandoLength = expando.length;
|
||||
setCurrentDirectiveDef(def);
|
||||
def.hostBindings !(RenderFlags.Create, directive, tNode.index);
|
||||
def.hostBindings !(RenderFlags.Create, directive, tNode.index - HEADER_OFFSET);
|
||||
setCurrentDirectiveDef(null);
|
||||
// `hostBindings` function may or may not contain `allocHostVars` call
|
||||
// (e.g. it may not if it only contains host listeners), so we need to check whether
|
||||
|
|
|
@ -54,7 +54,7 @@ describe('host bindings', () => {
|
|||
allocHostVars(1);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
elementProperty(elementIndex, 'id', bind(ctx.id));
|
||||
elementProperty(elementIndex, 'id', bind(ctx.id), null, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -75,7 +75,7 @@ describe('host bindings', () => {
|
|||
allocHostVars(1);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
elementProperty(elIndex, 'id', bind(ctx.id));
|
||||
elementProperty(elIndex, 'id', bind(ctx.id), null, true);
|
||||
}
|
||||
},
|
||||
template: (rf: RenderFlags, ctx: HostBindingComp) => {}
|
||||
|
@ -84,7 +84,7 @@ describe('host bindings', () => {
|
|||
|
||||
it('should support host bindings in directives', () => {
|
||||
let directiveInstance: Directive|undefined;
|
||||
|
||||
const elementIndices: number[] = [];
|
||||
class Directive {
|
||||
// @HostBinding('className')
|
||||
klass = 'foo';
|
||||
|
@ -94,11 +94,12 @@ describe('host bindings', () => {
|
|||
selectors: [['', 'dir', '']],
|
||||
factory: () => directiveInstance = new Directive,
|
||||
hostBindings: (rf: RenderFlags, ctx: any, elementIndex: number) => {
|
||||
elementIndices.push(elementIndex);
|
||||
if (rf & RenderFlags.Create) {
|
||||
allocHostVars(1);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
elementProperty(elementIndex, 'className', bind(ctx.klass));
|
||||
elementProperty(elementIndex, 'className', bind(ctx.klass), null, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -112,15 +113,46 @@ describe('host bindings', () => {
|
|||
directiveInstance !.klass = 'bar';
|
||||
fixture.update();
|
||||
expect(fixture.html).toEqual('<span class="bar"></span>');
|
||||
|
||||
// verify that we always call `hostBindings` function with the same element index
|
||||
expect(elementIndices.every(id => id === elementIndices[0])).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should support host bindings on root component', () => {
|
||||
const elementIndices: number[] = [];
|
||||
|
||||
class HostBindingComp {
|
||||
// @HostBinding()
|
||||
id = 'my-id';
|
||||
|
||||
static ngComponentDef = defineComponent({
|
||||
type: HostBindingComp,
|
||||
selectors: [['host-binding-comp']],
|
||||
factory: () => new HostBindingComp(),
|
||||
consts: 0,
|
||||
vars: 0,
|
||||
hostBindings: (rf: RenderFlags, ctx: HostBindingComp, elIndex: number) => {
|
||||
elementIndices.push(elIndex);
|
||||
if (rf & RenderFlags.Create) {
|
||||
allocHostVars(1);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
elementProperty(elIndex, 'id', bind(ctx.id), null, true);
|
||||
}
|
||||
},
|
||||
template: (rf: RenderFlags, ctx: HostBindingComp) => {}
|
||||
});
|
||||
}
|
||||
|
||||
const fixture = new ComponentFixture(HostBindingComp);
|
||||
expect(fixture.hostElement.id).toBe('my-id');
|
||||
|
||||
fixture.component.id = 'other-id';
|
||||
fixture.update();
|
||||
expect(fixture.hostElement.id).toBe('other-id');
|
||||
|
||||
// verify that we always call `hostBindings` function with the same element index
|
||||
expect(elementIndices.every(id => id === elementIndices[0])).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should support host bindings on nodes with providers', () => {
|
||||
|
@ -150,7 +182,7 @@ describe('host bindings', () => {
|
|||
allocHostVars(1);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
elementProperty(elIndex, 'id', bind(ctx.id));
|
||||
elementProperty(elIndex, 'id', bind(ctx.id), null, true);
|
||||
}
|
||||
},
|
||||
template: (rf: RenderFlags, ctx: CompWithProviders) => {},
|
||||
|
@ -186,7 +218,7 @@ describe('host bindings', () => {
|
|||
allocHostVars(1);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
elementProperty(elIndex, 'title', bind(ctx.title));
|
||||
elementProperty(elIndex, 'title', bind(ctx.title), null, true);
|
||||
}
|
||||
},
|
||||
template: (rf: RenderFlags, ctx: HostTitleComp) => {}
|
||||
|
@ -239,7 +271,7 @@ describe('host bindings', () => {
|
|||
allocHostVars(1);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
elementProperty(elIndex, 'id', bind(ctx.id));
|
||||
elementProperty(elIndex, 'id', bind(ctx.id), null, true);
|
||||
}
|
||||
},
|
||||
template: (rf: RenderFlags, ctx: HostBindingComp) => {}
|
||||
|
@ -329,7 +361,7 @@ describe('host bindings', () => {
|
|||
allocHostVars(1);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
elementProperty(elIndex, 'title', bind(ctx.value));
|
||||
elementProperty(elIndex, 'title', bind(ctx.value), null, true);
|
||||
}
|
||||
},
|
||||
inputs: {inputValue: 'inputValue'}
|
||||
|
@ -562,10 +594,11 @@ describe('host bindings', () => {
|
|||
allocHostVars(8);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
elementProperty(elIndex, 'id', bind(pureFunction1(3, ff, ctx.id)));
|
||||
elementProperty(elIndex, 'dir', bind(ctx.dir));
|
||||
elementProperty(elIndex, 'id', bind(pureFunction1(3, ff, ctx.id)), null, true);
|
||||
elementProperty(elIndex, 'dir', bind(ctx.dir), null, true);
|
||||
elementProperty(
|
||||
elIndex, 'title', bind(pureFunction2(5, ff2, ctx.title, ctx.otherTitle)));
|
||||
elIndex, 'title', bind(pureFunction2(5, ff2, ctx.title, ctx.otherTitle)), null,
|
||||
true);
|
||||
}
|
||||
},
|
||||
template: (rf: RenderFlags, ctx: HostBindingComp) => {}
|
||||
|
@ -640,7 +673,7 @@ describe('host bindings', () => {
|
|||
allocHostVars(3);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
elementProperty(elIndex, 'id', bind(pureFunction1(1, ff, ctx.id)));
|
||||
elementProperty(elIndex, 'id', bind(pureFunction1(1, ff, ctx.id)), null, true);
|
||||
}
|
||||
},
|
||||
template: (rf: RenderFlags, ctx: HostBindingComp) => {}
|
||||
|
@ -671,7 +704,7 @@ describe('host bindings', () => {
|
|||
allocHostVars(3);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
elementProperty(elIndex, 'title', bind(pureFunction1(1, ff1, ctx.title)));
|
||||
elementProperty(elIndex, 'title', bind(pureFunction1(1, ff1, ctx.title)), null, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -728,7 +761,7 @@ describe('host bindings', () => {
|
|||
allocHostVars(3);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
elementProperty(elIndex, 'title', bind(pureFunction1(1, ff1, ctx.title)));
|
||||
elementProperty(elIndex, 'title', bind(pureFunction1(1, ff1, ctx.title)), null, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -799,10 +832,12 @@ describe('host bindings', () => {
|
|||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
elementProperty(
|
||||
elIndex, 'id', bind(ctx.condition ? pureFunction1(2, ff, ctx.id) : 'green'));
|
||||
elIndex, 'id', bind(ctx.condition ? pureFunction1(2, ff, ctx.id) : 'green'), null,
|
||||
true);
|
||||
elementProperty(
|
||||
elIndex, 'title',
|
||||
bind(ctx.otherCondition ? pureFunction1(4, ff1, ctx.title) : 'other title'));
|
||||
bind(ctx.otherCondition ? pureFunction1(4, ff1, ctx.title) : 'other title'), null,
|
||||
true);
|
||||
}
|
||||
},
|
||||
template: (rf: RenderFlags, ctx: HostBindingComp) => {}
|
||||
|
@ -859,7 +894,7 @@ describe('host bindings', () => {
|
|||
allocHostVars(1);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
elementProperty(elementIndex, 'id', bind(ctx.id));
|
||||
elementProperty(elementIndex, 'id', bind(ctx.id), null, true);
|
||||
}
|
||||
},
|
||||
factory: () => superDir = new SuperDirective(),
|
||||
|
@ -877,7 +912,7 @@ describe('host bindings', () => {
|
|||
allocHostVars(1);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
elementProperty(elementIndex, 'title', bind(ctx.title));
|
||||
elementProperty(elementIndex, 'title', bind(ctx.title), null, true);
|
||||
}
|
||||
},
|
||||
factory: () => subDir = new SubDirective(),
|
||||
|
@ -965,7 +1000,7 @@ describe('host bindings', () => {
|
|||
allocHostVars(1);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
elementProperty(elIndex, 'id', bind(ctx.foos.length));
|
||||
elementProperty(elIndex, 'id', bind(ctx.foos.length), null, true);
|
||||
}
|
||||
},
|
||||
contentQueries: (dirIndex) => { registerContentQuery(query(null, ['foo']), dirIndex); },
|
||||
|
@ -1024,7 +1059,7 @@ describe('host bindings', () => {
|
|||
allocHostVars(1);
|
||||
}
|
||||
if (rf & RenderFlags.Update) {
|
||||
elementProperty(elIndex, 'id', bind(ctx.myValue));
|
||||
elementProperty(elIndex, 'id', bind(ctx.myValue), null, true);
|
||||
}
|
||||
},
|
||||
template: (rf: RenderFlags, cmp: HostBindingWithContentHooks) => {}
|
||||
|
|
Loading…
Reference in New Issue