[FIX] observer: better handling of reassigning state

closes #50
This commit is contained in:
Géry Debongnie
2019-04-18 11:30:33 +02:00
parent d9d109c9a2
commit 4fb2733321
2 changed files with 31 additions and 20 deletions
+2 -8
View File
@@ -73,6 +73,7 @@ export class Observer {
}
if ("__owl__" in value) {
// already observed
value.__owl__.parent = parent;
return;
}
if (Array.isArray(value)) {
@@ -88,12 +89,6 @@ export class Observer {
this.notifyChange();
}
unobserve(target: any) {
if (target !== null && typeof target === "object") {
delete target.__owl__;
}
}
_observeObj<T extends { __owl__?: any }>(obj: T, parent?: any) {
const keys = Object.keys(obj);
obj.__owl__ = { rev: 1, deepRev: 1, parent };
@@ -131,14 +126,13 @@ export class Observer {
`Observed state cannot be changed here! (key: "${key}", val: "${newVal}")`
);
}
self.unobserve(value);
value = newVal;
self.observe(newVal, obj);
obj.__owl__.rev!++;
let parent = obj;
do {
parent.__owl__.deepRev++;
} while ((parent = parent.__owl__.parent));
} while ((parent = parent.__owl__.parent) && parent !== obj);
self.notifyChange();
}
}
+29 -12
View File
@@ -172,18 +172,6 @@ describe("observer", () => {
expect(state.a.__owl__.rev).toBe(2);
});
test("properly unobserve objects in object", () => {
const observer = new Observer();
const state: any = { a: { b: 1 } };
observer.observe(state);
expect(state.__owl__.rev).toBe(1);
const initialA = state.a;
expect(initialA.__owl__.rev).toBe(1);
state.a = "Karlsquell";
expect(initialA.__owl__).not.toBeDefined();
});
test("reobserve new object values", () => {
const observer = new Observer();
const obj: any = { a: 1 };
@@ -240,6 +228,35 @@ describe("observer", () => {
expect(obj2.__owl__.rev).toBe(3);
});
test("properly handle swapping elements", () => {
const observer = new Observer();
const obj: any = { a: { arr: [] }, b: 1 };
observer.observe(obj);
// swap a and b
const b = obj.b;
obj.b = obj.a;
obj.a = b;
expect(observer.rev).toBe(3);
// push something into array to make sure it works
obj.b.arr.push("blanche");
expect(observer.rev).toBe(4);
});
test("properly handle assigning observed obj containing array", () => {
const observer = new Observer();
const obj: any = { a: { arr: [], val: "test" } };
observer.observe(obj);
obj.a = { ...obj.a, val: "test2" };
expect(observer.rev).toBe(2);
// push something into array to make sure it works
obj.a.arr.push("blanche");
expect(observer.rev).toBe(3);
});
test("accept cycles in observed state", () => {
const observer = new Observer();
const obj1: any = {};