fix(core): only apply WrappedValue
to the binding of the pipe (#15257)
Previously, a pipe that returned a `WrappedValue` would force the change of the next bound property, independent of the binding in which the pipe was used. Now only the binding in which the `WrappedValue` is used will be assumed as changed. Fixes #15116 PR Close #15257
This commit is contained in:

committed by
Miško Hevery

parent
49829b4a4d
commit
0c43535ccc
@ -6,7 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {ChangeDetectorRef, SimpleChange, SimpleChanges} from '../change_detection/change_detection';
|
||||
import {ChangeDetectorRef, SimpleChange, SimpleChanges, WrappedValue} from '../change_detection/change_detection';
|
||||
import {Injector} from '../di';
|
||||
import {ElementRef} from '../linker/element_ref';
|
||||
import {TemplateRef} from '../linker/template_ref';
|
||||
@ -450,7 +450,10 @@ function updateProp(
|
||||
providerData.instance[propName] = value;
|
||||
if (def.flags & NodeFlags.OnChanges) {
|
||||
changes = changes || {};
|
||||
const oldValue = view.oldValues[def.bindingIndex + bindingIdx];
|
||||
let oldValue = view.oldValues[def.bindingIndex + bindingIdx];
|
||||
if (oldValue instanceof WrappedValue) {
|
||||
oldValue = oldValue.wrapped;
|
||||
}
|
||||
const binding = def.bindings[bindingIdx];
|
||||
changes[binding.nonMinifiedName] =
|
||||
new SimpleChange(oldValue, value, (view.state & ViewState.FirstCheck) !== 0);
|
||||
|
@ -32,12 +32,15 @@ export function tokenKey(token: any): string {
|
||||
return key;
|
||||
}
|
||||
|
||||
let unwrapCounter = 0;
|
||||
|
||||
export function unwrapValue(value: any): any {
|
||||
export function unwrapValue(view: ViewData, nodeIdx: number, bindingIdx: number, value: any): any {
|
||||
if (value instanceof WrappedValue) {
|
||||
value = value.wrapped;
|
||||
unwrapCounter++;
|
||||
let globalBindingIdx = view.def.nodes[nodeIdx].bindingIndex + bindingIdx;
|
||||
let oldValue = view.oldValues[globalBindingIdx];
|
||||
if (oldValue instanceof WrappedValue) {
|
||||
oldValue = oldValue.wrapped;
|
||||
}
|
||||
view.oldValues[globalBindingIdx] = new WrappedValue(oldValue);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@ -83,9 +86,8 @@ export function resolveRendererType2(type: RendererType2): RendererType2 {
|
||||
export function checkBinding(
|
||||
view: ViewData, def: NodeDef, bindingIdx: number, value: any): boolean {
|
||||
const oldValues = view.oldValues;
|
||||
if (unwrapCounter > 0 || !!(view.state & ViewState.FirstCheck) ||
|
||||
if ((view.state & ViewState.FirstCheck) ||
|
||||
!looseIdentical(oldValues[def.bindingIndex + bindingIdx], value)) {
|
||||
unwrapCounter = 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -103,8 +105,7 @@ export function checkAndUpdateBinding(
|
||||
export function checkBindingNoChanges(
|
||||
view: ViewData, def: NodeDef, bindingIdx: number, value: any) {
|
||||
const oldValue = view.oldValues[def.bindingIndex + bindingIdx];
|
||||
if (unwrapCounter || (view.state & ViewState.FirstCheck) || !devModeEqual(oldValue, value)) {
|
||||
unwrapCounter = 0;
|
||||
if ((view.state & ViewState.FirstCheck) || !devModeEqual(oldValue, value)) {
|
||||
throw expressionChangedAfterItHasBeenCheckedError(
|
||||
Services.createDebugContext(view, def.index), oldValue, value,
|
||||
(view.state & ViewState.FirstCheck) !== 0);
|
||||
|
Reference in New Issue
Block a user