fix(ivy): pipe returning WrappedValue should invalidate correct binding (#28044)
When a pipe returns an instance of WrappedValue we should "invalidate" value of a binding where the pipe in question is used. Before this change we've always wrtten the invalidation value (NO_CHANGE) to the binding root this invalidating the first binding in a LView. This commit corrects the binding index calculation so the binding with a pipe is invalidated. PR Close #28044
This commit is contained in:
parent
dffcb9cda3
commit
afaea110c7
|
@ -11,9 +11,9 @@ import {PipeTransform} from '../change_detection/pipe_transform';
|
||||||
|
|
||||||
import {load, store} from './instructions';
|
import {load, store} from './instructions';
|
||||||
import {PipeDef, PipeDefList} from './interfaces/definition';
|
import {PipeDef, PipeDefList} from './interfaces/definition';
|
||||||
import {HEADER_OFFSET, TVIEW} from './interfaces/view';
|
import {BINDING_INDEX, HEADER_OFFSET, TVIEW} from './interfaces/view';
|
||||||
import {pureFunction1, pureFunction2, pureFunction3, pureFunction4, pureFunctionV} from './pure_function';
|
import {pureFunction1, pureFunction2, pureFunction3, pureFunction4, pureFunctionV} from './pure_function';
|
||||||
import {getBindingRoot, getLView} from './state';
|
import {getLView} from './state';
|
||||||
import {NO_CHANGE} from './tokens';
|
import {NO_CHANGE} from './tokens';
|
||||||
|
|
||||||
|
|
||||||
|
@ -171,7 +171,11 @@ function isPure(index: number): boolean {
|
||||||
function unwrapValue(newValue: any): any {
|
function unwrapValue(newValue: any): any {
|
||||||
if (WrappedValue.isWrapped(newValue)) {
|
if (WrappedValue.isWrapped(newValue)) {
|
||||||
newValue = WrappedValue.unwrap(newValue);
|
newValue = WrappedValue.unwrap(newValue);
|
||||||
getLView()[getBindingRoot()] = NO_CHANGE;
|
const lView = getLView();
|
||||||
|
// The NO_CHANGE value needs to be written at the index where the impacted binding value is
|
||||||
|
// stored
|
||||||
|
const bindingToInvalidateIdx = lView[BINDING_INDEX];
|
||||||
|
lView[bindingToInvalidateIdx] = NO_CHANGE;
|
||||||
}
|
}
|
||||||
return newValue;
|
return newValue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -537,28 +537,27 @@ const TEST_COMPILER_PROVIDERS: Provider[] = [
|
||||||
expect(renderLog.log).toEqual(['someProp=Megatron']);
|
expect(renderLog.log).toEqual(['someProp=Megatron']);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
fixmeIvy('FW-820: Pipes returning WrappedValue corrupt unrelated bindings ')
|
it('should record unwrapped values via ngOnChanges', fakeAsync(() => {
|
||||||
.it('should record unwrapped values via ngOnChanges', fakeAsync(() => {
|
const ctx = createCompFixture(
|
||||||
const ctx = createCompFixture(
|
'<div [testDirective]="\'aName\' | wrappedPipe" [a]="1" [b]="2 | wrappedPipe"></div>');
|
||||||
'<div [testDirective]="\'aName\' | wrappedPipe" [a]="1" [b]="2 | wrappedPipe"></div>');
|
const dir: TestDirective = queryDirs(ctx.debugElement, TestDirective)[0];
|
||||||
const dir: TestDirective = queryDirs(ctx.debugElement, TestDirective)[0];
|
ctx.detectChanges(false);
|
||||||
ctx.detectChanges(false);
|
dir.changes = {};
|
||||||
dir.changes = {};
|
ctx.detectChanges(false);
|
||||||
ctx.detectChanges(false);
|
|
||||||
|
|
||||||
// Note: the binding for `b` did not change and has no ValueWrapper,
|
// Note: the binding for `a` did not change and has no ValueWrapper,
|
||||||
// and should therefore stay unchanged.
|
// and should therefore stay unchanged.
|
||||||
expect(dir.changes).toEqual({
|
expect(dir.changes).toEqual({
|
||||||
'name': new SimpleChange('aName', 'aName', false),
|
'name': new SimpleChange('aName', 'aName', false),
|
||||||
'b': new SimpleChange(2, 2, false)
|
'b': new SimpleChange(2, 2, false)
|
||||||
});
|
});
|
||||||
|
|
||||||
ctx.detectChanges(false);
|
ctx.detectChanges(false);
|
||||||
expect(dir.changes).toEqual({
|
expect(dir.changes).toEqual({
|
||||||
'name': new SimpleChange('aName', 'aName', false),
|
'name': new SimpleChange('aName', 'aName', false),
|
||||||
'b': new SimpleChange(2, 2, false)
|
'b': new SimpleChange(2, 2, false)
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should call pure pipes only if the arguments change', fakeAsync(() => {
|
it('should call pure pipes only if the arguments change', fakeAsync(() => {
|
||||||
const ctx = _bindSimpleValue('name | countingPipe', Person);
|
const ctx = _bindSimpleValue('name | countingPipe', Person);
|
||||||
|
|
Loading…
Reference in New Issue