fix(change_detection): updated dynamic change detector not to mutate when throwing
Closes #1762
This commit is contained in:
parent
c68fa27444
commit
d717529e9a
|
@ -90,9 +90,8 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
|
||||||
var bindingRecord = proto.bindingRecord;
|
var bindingRecord = proto.bindingRecord;
|
||||||
var directiveRecord = bindingRecord.directiveRecord;
|
var directiveRecord = bindingRecord.directiveRecord;
|
||||||
|
|
||||||
var change = this._check(proto);
|
var change = this._check(proto, throwOnChange);
|
||||||
if (isPresent(change)) {
|
if (isPresent(change)) {
|
||||||
if (throwOnChange) ChangeDetectionUtil.throwOnChange(proto, change);
|
|
||||||
this._updateDirectiveOrElement(change, bindingRecord);
|
this._updateDirectiveOrElement(change, bindingRecord);
|
||||||
isChanged = true;
|
isChanged = true;
|
||||||
changes = this._addChange(bindingRecord, change, changes);
|
changes = this._addChange(bindingRecord, change, changes);
|
||||||
|
@ -144,19 +143,19 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
|
||||||
|
|
||||||
_getDetectorFor(directiveIndex) { return this.directives.getDetectorFor(directiveIndex); }
|
_getDetectorFor(directiveIndex) { return this.directives.getDetectorFor(directiveIndex); }
|
||||||
|
|
||||||
_check(proto: ProtoRecord): SimpleChange {
|
_check(proto: ProtoRecord, throwOnChange: boolean): SimpleChange {
|
||||||
try {
|
try {
|
||||||
if (proto.mode === RECORD_TYPE_PIPE || proto.mode === RECORD_TYPE_BINDING_PIPE) {
|
if (proto.mode === RECORD_TYPE_PIPE || proto.mode === RECORD_TYPE_BINDING_PIPE) {
|
||||||
return this._pipeCheck(proto);
|
return this._pipeCheck(proto, throwOnChange);
|
||||||
} else {
|
} else {
|
||||||
return this._referenceCheck(proto);
|
return this._referenceCheck(proto, throwOnChange);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new ChangeDetectionError(proto, e);
|
throw new ChangeDetectionError(proto, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_referenceCheck(proto: ProtoRecord) {
|
_referenceCheck(proto: ProtoRecord, throwOnChange: boolean) {
|
||||||
if (this._pureFuncAndArgsDidNotChange(proto)) {
|
if (this._pureFuncAndArgsDidNotChange(proto)) {
|
||||||
this._setChanged(proto, false);
|
this._setChanged(proto, false);
|
||||||
return null;
|
return null;
|
||||||
|
@ -166,12 +165,18 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
|
||||||
var currValue = this._calculateCurrValue(proto);
|
var currValue = this._calculateCurrValue(proto);
|
||||||
|
|
||||||
if (!isSame(prevValue, currValue)) {
|
if (!isSame(prevValue, currValue)) {
|
||||||
this._writeSelf(proto, currValue);
|
|
||||||
this._setChanged(proto, true);
|
|
||||||
|
|
||||||
if (proto.lastInBinding) {
|
if (proto.lastInBinding) {
|
||||||
return ChangeDetectionUtil.simpleChange(prevValue, currValue);
|
var change = ChangeDetectionUtil.simpleChange(prevValue, currValue);
|
||||||
|
if (throwOnChange) ChangeDetectionUtil.throwOnChange(proto, change);
|
||||||
|
|
||||||
|
this._writeSelf(proto, currValue);
|
||||||
|
this._setChanged(proto, true);
|
||||||
|
|
||||||
|
return change;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
this._writeSelf(proto, currValue);
|
||||||
|
this._setChanged(proto, true);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -216,22 +221,28 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_pipeCheck(proto: ProtoRecord) {
|
_pipeCheck(proto: ProtoRecord, throwOnChange: boolean) {
|
||||||
var context = this._readContext(proto);
|
var context = this._readContext(proto);
|
||||||
var pipe = this._pipeFor(proto, context);
|
var pipe = this._pipeFor(proto, context);
|
||||||
var prevValue = this._readSelf(proto);
|
var prevValue = this._readSelf(proto);
|
||||||
|
|
||||||
var newValue = pipe.transform(context);
|
var currValue = pipe.transform(context);
|
||||||
|
|
||||||
if (!isSame(prevValue, newValue)) {
|
if (!isSame(prevValue, currValue)) {
|
||||||
newValue = ChangeDetectionUtil.unwrapValue(newValue);
|
currValue = ChangeDetectionUtil.unwrapValue(currValue);
|
||||||
|
|
||||||
this._writeSelf(proto, newValue);
|
|
||||||
this._setChanged(proto, true);
|
|
||||||
|
|
||||||
if (proto.lastInBinding) {
|
if (proto.lastInBinding) {
|
||||||
return ChangeDetectionUtil.simpleChange(prevValue, newValue);
|
var change = ChangeDetectionUtil.simpleChange(prevValue, currValue);
|
||||||
|
if (throwOnChange) ChangeDetectionUtil.throwOnChange(proto, change);
|
||||||
|
|
||||||
|
this._writeSelf(proto, currValue);
|
||||||
|
this._setChanged(proto, true);
|
||||||
|
|
||||||
|
return change;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
this._writeSelf(proto, currValue);
|
||||||
|
this._setChanged(proto, true);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -420,6 +420,23 @@ export function main() {
|
||||||
cd.checkNoChanges();
|
cd.checkNoChanges();
|
||||||
}).toThrowError(new RegExp("Expression 'a in location' has changed after it was checked"));
|
}).toThrowError(new RegExp("Expression 'a in location' has changed after it was checked"));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should not break the next run", () => {
|
||||||
|
var pcd = createProtoChangeDetector([
|
||||||
|
BindingRecord.createForElement(ast("a"), 0, "a")
|
||||||
|
]);
|
||||||
|
|
||||||
|
var dispatcher = new TestDispatcher();
|
||||||
|
var cd = pcd.instantiate(dispatcher);
|
||||||
|
cd.hydrate(new TestData('value'), null, null);
|
||||||
|
|
||||||
|
expect(() => cd.checkNoChanges()).toThrowError(new RegExp(
|
||||||
|
"Expression 'a in location' has changed after it was checked."));
|
||||||
|
|
||||||
|
cd.detectChanges();
|
||||||
|
|
||||||
|
expect(dispatcher.loggedValues).toEqual(['value']);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
//TODO vsavkin: implement it
|
//TODO vsavkin: implement it
|
||||||
|
|
Loading…
Reference in New Issue