refactor(ivy): move bindingIndex from LView to LFrame (#33235)

`bindingIndex` stores the current location of the bindings in the
template function. Because it used to be stored in `LView` that `LView`
was not reentrant. This could happen if a binding was a getter and had
a side-effect of calling `detectChanges()`.

By moving the `bindingIndex` to `LFrame` where all of the global state
is kept in reentrant way we correct the issue.

PR Close #33235
This commit is contained in:
Miško Hevery
2019-10-11 12:43:32 -07:00
committed by Andrew Kushnir
parent c61f413477
commit e16f75db56
22 changed files with 204 additions and 138 deletions

View File

@ -127,6 +127,53 @@ describe('change detection', () => {
fixture.detectChanges(false);
expect(fixture.nativeElement).toHaveText('1|dynamic');
});
it('should support re-enterant change detection', () => {
@Component({
selector: 'has-host-binding',
template: '..',
host: {
'[class.x]': 'x',
}
})
class HasHostBinding {
x = true;
}
@Component({
selector: 'child',
template: '<has-host-binding></has-host-binding>',
inputs: ['input'],
})
class Child {
/**
* @internal
*/
private _input !: number;
constructor(private cdr: ChangeDetectorRef) {}
get input() { return this._input; }
set input(value: number) {
this._input = value;
this.cdr.detectChanges();
}
}
@Component({
selector: 'root',
template: '<child [input]="3"></child>',
})
class Root {
}
TestBed.configureTestingModule({
declarations: [Root, Child, HasHostBinding],
});
TestBed.createComponent(Root).detectChanges();
});
});
describe('OnPush', () => {

View File

@ -2,9 +2,6 @@
{
"name": "ACTIVE_INDEX"
},
{
"name": "BINDING_INDEX"
},
{
"name": "BLOOM_MASK"
},
@ -608,6 +605,9 @@
{
"name": "setActiveHostElement"
},
{
"name": "setBindingIndex"
},
{
"name": "setBindingRoot"
},

View File

@ -2,9 +2,6 @@
{
"name": "ACTIVE_INDEX"
},
{
"name": "BINDING_INDEX"
},
{
"name": "BLOOM_MASK"
},
@ -437,6 +434,9 @@
{
"name": "setActiveHostElement"
},
{
"name": "setBindingIndex"
},
{
"name": "setBindingRoot"
},

View File

@ -2,9 +2,6 @@
{
"name": "ACTIVE_INDEX"
},
{
"name": "BINDING_INDEX"
},
{
"name": "BIT_MASK_START_VALUE"
},
@ -611,9 +608,6 @@
{
"name": "getActiveDirectiveId"
},
{
"name": "getAndIncrementBindingIndex"
},
{
"name": "getBeforeNodeForView"
},
@ -1073,6 +1067,9 @@
{
"name": "nativeRemoveNode"
},
{
"name": "nextBindingIndex"
},
{
"name": "nextContextImpl"
},
@ -1208,6 +1205,9 @@
{
"name": "setActiveHostElement"
},
{
"name": "setBindingIndex"
},
{
"name": "setBindingRoot"
},