fix(ivy): improve ExpressionChangedAfterChecked error (#34381)

Prior to this change, the ExpressionChangedAfterChecked error thrown in Ivy was missing useful information that was available in View Engine, specifically: missing property name for proprty bindings and also the content of the entire property interpolation (only a changed value was displayed) if one of expressions was changed unexpectedly. This commit improves the error message by including the mentioned information into the error text.

PR Close #34381
This commit is contained in:
Andrew Kushnir
2019-12-10 16:23:56 -08:00
committed by Kara Erickson
parent 3e201181bb
commit 9d1175e2b2
4 changed files with 257 additions and 20 deletions

View File

@ -20,7 +20,7 @@ import {activateStylingMapFeature} from '../styling/map_based_bindings';
import {attachStylingDebugObject} from '../styling/styling_debug';
import {NO_CHANGE} from '../tokens';
import {renderStringify} from '../util/misc_utils';
import {addItemToStylingMap, allocStylingMapArray, allocTStylingContext, allowDirectStyling, concatString, forceClassesAsString, forceStylesAsString, getInitialStylingValue, getStylingMapArray, getValue, hasClassInput, hasStyleInput, hasValueChanged, hasValueChangedUnwrapSafeValue, isHostStylingActive, isStylingContext, isStylingValueDefined, normalizeIntoStylingMap, patchConfig, selectClassBasedInputName, setValue, stylingMapToString} from '../util/styling_utils';
import {addItemToStylingMap, allocStylingMapArray, allocTStylingContext, allowDirectStyling, concatString, forceClassesAsString, forceStylesAsString, getInitialStylingValue, getStylingMapArray, getValue, hasClassInput, hasStyleInput, hasValueChanged, hasValueChangedUnwrapSafeValue, isHostStylingActive, isStylingContext, isStylingMapArray, isStylingValueDefined, normalizeIntoStylingMap, patchConfig, selectClassBasedInputName, setValue, stylingMapToString} from '../util/styling_utils';
import {getNativeByTNode, getTNode} from '../util/view_utils';
@ -191,7 +191,8 @@ function stylingProp(
if (ngDevMode && getCheckNoChangesMode()) {
const oldValue = getValue(lView, bindingIndex);
if (hasValueChangedUnwrapSafeValue(oldValue, value)) {
throwErrorIfNoChangesMode(false, oldValue, value);
const field = isClassBased ? `class.${prop}` : `style.${prop}`;
throwErrorIfNoChangesMode(false, oldValue, value, field);
}
}
@ -369,7 +370,11 @@ function stylingMap(
// For this reason, the checkNoChanges situation must also be handled here
// as well.
if (ngDevMode && valueHasChanged && getCheckNoChangesMode()) {
throwErrorIfNoChangesMode(false, oldValue, value);
// check if the value is a StylingMapArray, in which case take the first value (which stores raw
// value) from the array
const previousValue =
isStylingMapArray(oldValue) ? oldValue[StylingMapArrayIndex.RawValuePosition] : oldValue;
throwErrorIfNoChangesMode(false, previousValue, value);
}
// Direct Apply Case: bypass context resolution and apply the