From 4fb2733321be1fe228afda2e31bfbda86f5c9a63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Debongnie?= Date: Thu, 18 Apr 2019 11:30:33 +0200 Subject: [PATCH] [FIX] observer: better handling of reassigning state closes #50 --- src/observer.ts | 10 ++-------- tests/observer.test.ts | 41 +++++++++++++++++++++++++++++------------ 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/src/observer.ts b/src/observer.ts index 3883c717..7281f3f8 100644 --- a/src/observer.ts +++ b/src/observer.ts @@ -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(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(); } } diff --git a/tests/observer.test.ts b/tests/observer.test.ts index 1c0dfdd5..9b58f397 100644 --- a/tests/observer.test.ts +++ b/tests/observer.test.ts @@ -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 = {};