feat(change_detection): allow all legal programs in the dev mode
BEFORE:
The following would throw in the dev mode because `f` would return a new array when called by checkNoChanges.
@Component({
template: `
{{f()}}
`
})
class A {
f() { return [1]; }
}
AFTER:
The checkNoChanges function compares only primitives types for equality, and deeply compares iterables. Other objects cannot cause checkNoChanges to throw. This means that the dev mode would never fail given a legal program, but may allow some illegal programs.
This commit is contained in:
@@ -887,6 +887,13 @@ export function main() {
|
||||
'Expression [\'"]a in location[\'"] has changed after it was checked'));
|
||||
});
|
||||
|
||||
it('should not throw when two arrays are structurally the same', () => {
|
||||
var val = _createChangeDetector('a', new TestDataWithGetter(() => ['value']));
|
||||
val.changeDetector.detectChanges();
|
||||
|
||||
expect(() => { val.changeDetector.checkNoChanges(); }).not.toThrow();
|
||||
});
|
||||
|
||||
it('should not break the next run', () => {
|
||||
var val = _createChangeDetector('a', new TestData('value'));
|
||||
expect(() => val.changeDetector.checkNoChanges())
|
||||
@@ -1597,6 +1604,12 @@ class TestData {
|
||||
constructor(public a: any) {}
|
||||
}
|
||||
|
||||
class TestDataWithGetter {
|
||||
constructor(private fn: Function) {}
|
||||
|
||||
get a() { return this.fn(); }
|
||||
}
|
||||
|
||||
class TestDispatcher implements ChangeDispatcher {
|
||||
log: string[];
|
||||
debugLog: string[];
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
import {
|
||||
ddescribe,
|
||||
describe,
|
||||
it,
|
||||
iit,
|
||||
xit,
|
||||
expect,
|
||||
beforeEach,
|
||||
afterEach
|
||||
} from 'angular2/testing_internal';
|
||||
|
||||
import {ChangeDetectionUtil} from 'angular2/src/core/change_detection/change_detection_util';
|
||||
|
||||
export function main() {
|
||||
describe("ChangeDetectionUtil", () => {
|
||||
describe("devModeEqual", () => {
|
||||
it("should do the deep comparison of iterables", () => {
|
||||
expect(ChangeDetectionUtil.devModeEqual([['one']], [['one']])).toBe(true);
|
||||
expect(ChangeDetectionUtil.devModeEqual(['one'], ['one', 'two'])).toBe(false);
|
||||
expect(ChangeDetectionUtil.devModeEqual(['one', 'two'], ['one'])).toBe(false);
|
||||
expect(ChangeDetectionUtil.devModeEqual(['one'], 'one')).toBe(false);
|
||||
expect(ChangeDetectionUtil.devModeEqual(['one'], new Object())).toBe(false);
|
||||
expect(ChangeDetectionUtil.devModeEqual('one', ['one'])).toBe(false);
|
||||
expect(ChangeDetectionUtil.devModeEqual(new Object(), ['one'])).toBe(false);
|
||||
});
|
||||
|
||||
it("should compare primitive numbers", () => {
|
||||
expect(ChangeDetectionUtil.devModeEqual(1, 1)).toBe(true);
|
||||
expect(ChangeDetectionUtil.devModeEqual(1, 2)).toBe(false);
|
||||
expect(ChangeDetectionUtil.devModeEqual(new Object(), 2)).toBe(false);
|
||||
expect(ChangeDetectionUtil.devModeEqual(1, new Object())).toBe(false);
|
||||
});
|
||||
|
||||
it("should compare primitive strings", () => {
|
||||
expect(ChangeDetectionUtil.devModeEqual('one', 'one')).toBe(true);
|
||||
expect(ChangeDetectionUtil.devModeEqual('one', 'two')).toBe(false);
|
||||
expect(ChangeDetectionUtil.devModeEqual(new Object(), 'one')).toBe(false);
|
||||
expect(ChangeDetectionUtil.devModeEqual('one', new Object())).toBe(false);
|
||||
});
|
||||
|
||||
it("should compare primitive booleans", () => {
|
||||
expect(ChangeDetectionUtil.devModeEqual(true, true)).toBe(true);
|
||||
expect(ChangeDetectionUtil.devModeEqual(true, false)).toBe(false);
|
||||
expect(ChangeDetectionUtil.devModeEqual(new Object(), true)).toBe(false);
|
||||
expect(ChangeDetectionUtil.devModeEqual(true, new Object())).toBe(false);
|
||||
});
|
||||
|
||||
it("should compare null", () => {
|
||||
expect(ChangeDetectionUtil.devModeEqual(null, null)).toBe(true);
|
||||
expect(ChangeDetectionUtil.devModeEqual(null, 1)).toBe(false);
|
||||
expect(ChangeDetectionUtil.devModeEqual(new Object(), null)).toBe(false);
|
||||
expect(ChangeDetectionUtil.devModeEqual(null, new Object())).toBe(false);
|
||||
});
|
||||
|
||||
it("should return true for other objects", () => {
|
||||
expect(ChangeDetectionUtil.devModeEqual(new Object(), new Object())).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user