diff --git a/src/observer.ts b/src/observer.ts index 016adfeb..efb1f67c 100644 --- a/src/observer.ts +++ b/src/observer.ts @@ -108,9 +108,15 @@ export class Observer { } set(target: any, key: number | string, value: any) { - this.rev++; - this._addProp(target, key, value); - target.__owl__.rev++; + let alreadyDefined = + key in target && + Object.getOwnPropertyDescriptor(target, key)!.configurable === false; + if (alreadyDefined) { + target[key] = value; + } else { + this._addProp(target, key, value); + this._updateRevNumber(target); + } this.notifyChange(); } @@ -145,23 +151,26 @@ export class Observer { }, set(newVal) { if (newVal !== value) { - self.rev++; if (!self.allowMutations) { throw new Error( `Observed state cannot be changed here! (key: "${key}", val: "${newVal}")` ); } + self._updateRevNumber(obj); value = newVal; self.observe(newVal, obj); - obj.__owl__.rev!++; - let parent = obj; - do { - parent.__owl__.deepRev++; - } while ((parent = parent.__owl__.parent) && parent !== obj); self.notifyChange(); } } }); this.observe(value, obj); } + _updateRevNumber(target: any) { + this.rev++; + target.__owl__.rev!++; + let parent = target; + do { + parent.__owl__.deepRev++; + } while ((parent = parent.__owl__.parent) && parent !== target); + } } diff --git a/tests/observer.test.ts b/tests/observer.test.ts index e165ae41..f1e15144 100644 --- a/tests/observer.test.ts +++ b/tests/observer.test.ts @@ -230,6 +230,26 @@ describe("observer", () => { expect(obj2.__owl__.rev).toBe(3); }); + test("can set a property more than once", () => { + const observer = new Observer(); + const obj: any = {}; + + observer.observe(obj); + expect(obj.__owl__.rev).toBe(1); + expect(observer.rev).toBe(1); + expect(obj.__owl__.deepRev).toBe(1); + + observer.set(obj, "aku", "always finds annoying problems"); + expect(observer.rev).toBe(2); + expect(obj.__owl__.rev).toBe(2); + expect(obj.__owl__.deepRev).toBe(2); + + observer.set(obj, "aku", "always finds good problems"); + expect(observer.rev).toBe(3); + expect(obj.__owl__.rev).toBe(3); + expect(obj.__owl__.deepRev).toBe(3); + }); + test("properly handle swapping elements", () => { const observer = new Observer(); const obj: any = { a: { arr: [] }, b: 1 };