Skip to content

Commit d717529

Browse files
vsavkinmhevery
authored andcommittedMay 8, 2015
fix(change_detection): updated dynamic change detector not to mutate when throwing
Closes #1762
1 parent c68fa27 commit d717529

File tree

2 files changed

+46
-18
lines changed

2 files changed

+46
-18
lines changed
 

‎modules/angular2/src/change_detection/dynamic_change_detector.ts

+29-18
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,8 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
9090
var bindingRecord = proto.bindingRecord;
9191
var directiveRecord = bindingRecord.directiveRecord;
9292

93-
var change = this._check(proto);
93+
var change = this._check(proto, throwOnChange);
9494
if (isPresent(change)) {
95-
if (throwOnChange) ChangeDetectionUtil.throwOnChange(proto, change);
9695
this._updateDirectiveOrElement(change, bindingRecord);
9796
isChanged = true;
9897
changes = this._addChange(bindingRecord, change, changes);
@@ -144,19 +143,19 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
144143

145144
_getDetectorFor(directiveIndex) { return this.directives.getDetectorFor(directiveIndex); }
146145

147-
_check(proto: ProtoRecord): SimpleChange {
146+
_check(proto: ProtoRecord, throwOnChange: boolean): SimpleChange {
148147
try {
149148
if (proto.mode === RECORD_TYPE_PIPE || proto.mode === RECORD_TYPE_BINDING_PIPE) {
150-
return this._pipeCheck(proto);
149+
return this._pipeCheck(proto, throwOnChange);
151150
} else {
152-
return this._referenceCheck(proto);
151+
return this._referenceCheck(proto, throwOnChange);
153152
}
154153
} catch (e) {
155154
throw new ChangeDetectionError(proto, e);
156155
}
157156
}
158157

159-
_referenceCheck(proto: ProtoRecord) {
158+
_referenceCheck(proto: ProtoRecord, throwOnChange: boolean) {
160159
if (this._pureFuncAndArgsDidNotChange(proto)) {
161160
this._setChanged(proto, false);
162161
return null;
@@ -166,12 +165,18 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
166165
var currValue = this._calculateCurrValue(proto);
167166

168167
if (!isSame(prevValue, currValue)) {
169-
this._writeSelf(proto, currValue);
170-
this._setChanged(proto, true);
171-
172168
if (proto.lastInBinding) {
173-
return ChangeDetectionUtil.simpleChange(prevValue, currValue);
169+
var change = ChangeDetectionUtil.simpleChange(prevValue, currValue);
170+
if (throwOnChange) ChangeDetectionUtil.throwOnChange(proto, change);
171+
172+
this._writeSelf(proto, currValue);
173+
this._setChanged(proto, true);
174+
175+
return change;
176+
174177
} else {
178+
this._writeSelf(proto, currValue);
179+
this._setChanged(proto, true);
175180
return null;
176181
}
177182
} else {
@@ -216,22 +221,28 @@ export class DynamicChangeDetector extends AbstractChangeDetector {
216221
}
217222
}
218223

219-
_pipeCheck(proto: ProtoRecord) {
224+
_pipeCheck(proto: ProtoRecord, throwOnChange: boolean) {
220225
var context = this._readContext(proto);
221226
var pipe = this._pipeFor(proto, context);
222227
var prevValue = this._readSelf(proto);
223228

224-
var newValue = pipe.transform(context);
229+
var currValue = pipe.transform(context);
225230

226-
if (!isSame(prevValue, newValue)) {
227-
newValue = ChangeDetectionUtil.unwrapValue(newValue);
228-
229-
this._writeSelf(proto, newValue);
230-
this._setChanged(proto, true);
231+
if (!isSame(prevValue, currValue)) {
232+
currValue = ChangeDetectionUtil.unwrapValue(currValue);
231233

232234
if (proto.lastInBinding) {
233-
return ChangeDetectionUtil.simpleChange(prevValue, newValue);
235+
var change = ChangeDetectionUtil.simpleChange(prevValue, currValue);
236+
if (throwOnChange) ChangeDetectionUtil.throwOnChange(proto, change);
237+
238+
this._writeSelf(proto, currValue);
239+
this._setChanged(proto, true);
240+
241+
return change;
242+
234243
} else {
244+
this._writeSelf(proto, currValue);
245+
this._setChanged(proto, true);
235246
return null;
236247
}
237248
} else {

‎modules/angular2/test/change_detection/change_detection_spec.js

+17
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,23 @@ export function main() {
420420
cd.checkNoChanges();
421421
}).toThrowError(new RegExp("Expression 'a in location' has changed after it was checked"));
422422
});
423+
424+
it("should not break the next run", () => {
425+
var pcd = createProtoChangeDetector([
426+
BindingRecord.createForElement(ast("a"), 0, "a")
427+
]);
428+
429+
var dispatcher = new TestDispatcher();
430+
var cd = pcd.instantiate(dispatcher);
431+
cd.hydrate(new TestData('value'), null, null);
432+
433+
expect(() => cd.checkNoChanges()).toThrowError(new RegExp(
434+
"Expression 'a in location' has changed after it was checked."));
435+
436+
cd.detectChanges();
437+
438+
expect(dispatcher.loggedValues).toEqual(['value']);
439+
});
423440
});
424441

425442
//TODO vsavkin: implement it

0 commit comments

Comments
 (0)