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 {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 {getBindingRoot, getLView} from './state';
|
||||
import {getLView} from './state';
|
||||
import {NO_CHANGE} from './tokens';
|
||||
|
||||
|
||||
|
@ -171,7 +171,11 @@ function isPure(index: number): boolean {
|
|||
function unwrapValue(newValue: any): any {
|
||||
if (WrappedValue.isWrapped(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;
|
||||
}
|
||||
|
|
|
@ -537,28 +537,27 @@ const TEST_COMPILER_PROVIDERS: Provider[] = [
|
|||
expect(renderLog.log).toEqual(['someProp=Megatron']);
|
||||
}));
|
||||
|
||||
fixmeIvy('FW-820: Pipes returning WrappedValue corrupt unrelated bindings ')
|
||||
.it('should record unwrapped values via ngOnChanges', fakeAsync(() => {
|
||||
const ctx = createCompFixture(
|
||||
'<div [testDirective]="\'aName\' | wrappedPipe" [a]="1" [b]="2 | wrappedPipe"></div>');
|
||||
const dir: TestDirective = queryDirs(ctx.debugElement, TestDirective)[0];
|
||||
ctx.detectChanges(false);
|
||||
dir.changes = {};
|
||||
ctx.detectChanges(false);
|
||||
it('should record unwrapped values via ngOnChanges', fakeAsync(() => {
|
||||
const ctx = createCompFixture(
|
||||
'<div [testDirective]="\'aName\' | wrappedPipe" [a]="1" [b]="2 | wrappedPipe"></div>');
|
||||
const dir: TestDirective = queryDirs(ctx.debugElement, TestDirective)[0];
|
||||
ctx.detectChanges(false);
|
||||
dir.changes = {};
|
||||
ctx.detectChanges(false);
|
||||
|
||||
// Note: the binding for `b` did not change and has no ValueWrapper,
|
||||
// and should therefore stay unchanged.
|
||||
expect(dir.changes).toEqual({
|
||||
'name': new SimpleChange('aName', 'aName', false),
|
||||
'b': new SimpleChange(2, 2, false)
|
||||
});
|
||||
// Note: the binding for `a` did not change and has no ValueWrapper,
|
||||
// and should therefore stay unchanged.
|
||||
expect(dir.changes).toEqual({
|
||||
'name': new SimpleChange('aName', 'aName', false),
|
||||
'b': new SimpleChange(2, 2, false)
|
||||
});
|
||||
|
||||
ctx.detectChanges(false);
|
||||
expect(dir.changes).toEqual({
|
||||
'name': new SimpleChange('aName', 'aName', false),
|
||||
'b': new SimpleChange(2, 2, false)
|
||||
});
|
||||
}));
|
||||
ctx.detectChanges(false);
|
||||
expect(dir.changes).toEqual({
|
||||
'name': new SimpleChange('aName', 'aName', false),
|
||||
'b': new SimpleChange(2, 2, false)
|
||||
});
|
||||
}));
|
||||
|
||||
it('should call pure pipes only if the arguments change', fakeAsync(() => {
|
||||
const ctx = _bindSimpleValue('name | countingPipe', Person);
|
||||
|
|
Loading…
Reference in New Issue