fix(ivy): host-styling throws assert exception inside *ngFor (#35133)
Inside `*ngFor` the second run of the styling instructions can get into situation where it tries to read a value from a binding which has not yet executed. As a result the read is `NO_CHANGE` value and subsequent property read cause an exception as it is of wrong type. Fix #35118 PR Close #35133
This commit is contained in:
@ -3273,6 +3273,52 @@ describe('styling', () => {
|
||||
|
||||
expect(logs).toEqual([]);
|
||||
});
|
||||
|
||||
describe('regression', () => {
|
||||
onlyInIvy('styling priority resolution is Ivy only feature.')
|
||||
.it('should allow lookahead binding on second pass #35118', () => {
|
||||
@Component({
|
||||
selector: 'my-cmp',
|
||||
template: ``,
|
||||
host: {
|
||||
'[class.foo]': 'hostClass',
|
||||
}
|
||||
})
|
||||
class MyCmp {
|
||||
hostClass = true;
|
||||
}
|
||||
|
||||
@Directive({
|
||||
selector: '[host-styling]',
|
||||
host: {
|
||||
'[class]': 'hostClass',
|
||||
}
|
||||
})
|
||||
class HostStylingsDir {
|
||||
hostClass = {'bar': true};
|
||||
}
|
||||
|
||||
@Component({template: `<my-cmp *ngFor="let i of [1,2]" host-styling></my-cmp>`})
|
||||
class MyApp {
|
||||
// When the first view in the list gets CD-ed, everything works.
|
||||
// When the second view gets CD-ed, the styling has already created the data structures
|
||||
// in the `TView`. As a result when
|
||||
// `[class.foo]` runs it already knows that `[class]` is a duplicate and hence it
|
||||
// should check with it. While the resolution is happening it reads the value of the
|
||||
// `[class]`, however `[class]` has not yet executed and therefore it does not have
|
||||
// normalized value in its `LView`. The result is that the assertions fails as it
|
||||
// expects an
|
||||
// `KeyValueArray`.
|
||||
}
|
||||
|
||||
TestBed.configureTestingModule({declarations: [MyApp, MyCmp, HostStylingsDir]});
|
||||
const fixture = TestBed.createComponent(MyApp);
|
||||
expect(() => fixture.detectChanges()).not.toThrow();
|
||||
const [cmp1, cmp2] = fixture.nativeElement.querySelectorAll('my-cmp');
|
||||
expectClass(cmp1).toEqual({foo: true, bar: true});
|
||||
expectClass(cmp2).toEqual({foo: true, bar: true});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function assertStyleCounters(countForSet: number, countForRemove: number) {
|
||||
|
Reference in New Issue
Block a user