diff --git a/src/store.ts b/src/store.ts index 051e236c..0d233970 100644 --- a/src/store.ts +++ b/src/store.ts @@ -67,7 +67,7 @@ export class Store extends EventBus { if (!this.mutations[type]) { throw new Error(`[Error] mutation ${type} is undefined`); } - const currentRev = this.observer.__rev__; + const currentRev = this.observer.rev; this._isMutating = true; this.observer.allowMutations = true; @@ -88,7 +88,7 @@ export class Store extends EventBus { await Promise.resolve(); if (this._isMutating) { this._isMutating = false; - if (currentRev !== this.observer.__rev__) { + if (currentRev !== this.observer.rev) { this.trigger("update", this.state); } } @@ -99,7 +99,7 @@ export class Store extends EventBus { // Observer //------------------------------------------------------------------------------ interface Observer { - __rev__: number; + rev: number; allowMutations: boolean; observe: (val: any) => void; set: (target: any, key: number | string, value: any) => void; @@ -107,7 +107,7 @@ interface Observer { export function makeObserver(): Observer { const observer: Observer = { - __rev__: 0, + rev: 1, allowMutations: true, observe: observe, set: set @@ -115,11 +115,11 @@ export function makeObserver(): Observer { function set(target: any, key: number | string, value: any) { addProp(target, key, value); - target.__rev__++; - observer.__rev__++; + target.__owl__.rev++; + observer.rev++; } - function addProp( + function addProp( obj: T, key: string | number, value: any @@ -138,18 +138,18 @@ export function makeObserver(): Observer { if (newVal !== value) { value = newVal; observe(newVal); - obj.__rev__!++; - observer.__rev__++; + obj.__owl__.rev!++; + observer.rev++; } } }); observe(value); } - function observeObj(obj: T) { + function observeObj(obj: T) { const keys = Object.keys(obj); - obj.__rev__ = 0; - Object.defineProperty(obj, "__rev__", { enumerable: false }); + obj.__owl__ = { rev: 1 }; + Object.defineProperty(obj, "__owl__", { enumerable: false }); for (let key of keys) { addProp(obj, key, obj[key]); } @@ -171,8 +171,8 @@ export function makeObserver(): Observer { for (let method of methodsToPatch) { const initialMethod = ArrayProto[method]; ModifiedArrayProto[method] = function(...args) { - observer.__rev__++; - this.__rev__++; + observer.rev++; + this.__owl__.rev++; let inserted; switch (method) { case "push": @@ -193,8 +193,8 @@ export function makeObserver(): Observer { } function observeArr(arr: Array) { - (arr).__rev__ = 0; - Object.defineProperty(arr, "__rev__", { enumerable: false }); + (arr).__owl__ = { rev: 1 }; + Object.defineProperty(arr, "__owl__", { enumerable: false }); (arr).__proto__ = ModifiedArrayProto; for (let i = 0; i < arr.length; i++) { observe(arr[i]); @@ -209,7 +209,7 @@ export function makeObserver(): Observer { if (typeof value !== "object") { return; } - if ("__rev__" in value) { + if ("__owl__" in value) { // already observed return; } @@ -230,9 +230,10 @@ export function makeObserver(): Observer { function setStoreProps(__owl__: any, storeProps: any) { __owl__.currentStoreProps = storeProps; __owl__.currentStoreRevs = {}; - __owl__.currentStoreRev = storeProps.__rev__; + __owl__.currentStoreRev = storeProps.__owl__ && storeProps.__owl__.rev; for (let key in storeProps) { - __owl__.currentStoreRevs[key] = storeProps[key].__rev__; + __owl__.currentStoreRevs[key] = + storeProps[key].__owl__ && storeProps[key].__owl__.rev; } } @@ -253,16 +254,19 @@ export function connect(mapStateToProps) { const ownProps = this.__owl__.ownProps; const storeProps = mapStateToProps(this.env.store.state, ownProps); let didChange = false; - if (this.__owl__.currentStoreRev !== storeProps.__rev__) { + if ( + this.__owl__.currentStoreRev && + this.__owl__.currentStoreRev !== storeProps.__owl__.rev + ) { setStoreProps(this.__owl__, storeProps); didChange = true; } else { const revs = this.__owl__.currentStoreRevs; for (let key in storeProps) { const val = storeProps[key]; - if (val.__rev__ !== revs[key]) { + if (val.__owl__ && val.__owl__.rev !== revs[key]) { didChange = true; - revs[key] = val.__rev__; + revs[key] = val.__owl__ && val.__owl__.rev; this.__owl__.currentStoreProps[key] = val; } } diff --git a/tests/store.test.ts b/tests/store.test.ts index 00d0943b..286529dc 100644 --- a/tests/store.test.ts +++ b/tests/store.test.ts @@ -143,23 +143,23 @@ describe("observer", () => { const obj: any = {}; observer.observe(obj); - expect(obj.__rev__).toBe(0); - expect(observer.__rev__).toBe(0); + expect(obj.__owl__.rev).toBe(1); + expect(observer.rev).toBe(1); const ob2: any = { a: 1 }; observer.observe(ob2); - expect(ob2.__rev__).toBe(0); + expect(ob2.__owl__.rev).toBe(1); ob2.a = 2; - expect(observer.__rev__).toBe(1); - expect(ob2.__rev__).toBe(1); + expect(observer.rev).toBe(2); + expect(ob2.__owl__.rev).toBe(2); ob2.b = 3; - expect(observer.__rev__).toBe(1); - expect(ob2.__rev__).toBe(1); + expect(observer.rev).toBe(2); + expect(ob2.__owl__.rev).toBe(2); observer.set(ob2, "b", 4); - expect(observer.__rev__).toBe(2); - expect(ob2.__rev__).toBe(2); + expect(observer.rev).toBe(3); + expect(ob2.__owl__.rev).toBe(3); }); test("properly handle null or undefined", () => { @@ -167,18 +167,18 @@ describe("observer", () => { const obj: any = { a: null, b: undefined }; observer.observe(obj); - expect(obj.__rev__).toBe(0); - expect(observer.__rev__).toBe(0); + expect(obj.__owl__.rev).toBe(1); + expect(observer.rev).toBe(1); obj.a = 3; - expect(obj.__rev__).toBe(1); + expect(obj.__owl__.rev).toBe(2); obj.b = 5; - expect(obj.__rev__).toBe(2); + expect(obj.__owl__.rev).toBe(3); obj.a = null; obj.b = undefined; - expect(obj.__rev__).toBe(4); + expect(obj.__owl__.rev).toBe(5); }); test("can change values in array", () => { @@ -186,69 +186,69 @@ describe("observer", () => { const obj: any = { arr: [1, 2] }; observer.observe(obj); - expect(obj.arr.__rev__).toBe(0); - expect(observer.__rev__).toBe(0); + expect(obj.arr.__owl__.rev).toBe(1); + expect(observer.rev).toBe(1); obj.arr[0] = "nope"; - expect(obj.arr.__rev__).toBe(0); - expect(observer.__rev__).toBe(0); + expect(obj.arr.__owl__.rev).toBe(1); + expect(observer.rev).toBe(1); observer.set(obj.arr, 0, "yep"); - expect(obj.arr.__rev__).toBe(1); - expect(observer.__rev__).toBe(1); + expect(obj.arr.__owl__.rev).toBe(2); + expect(observer.rev).toBe(2); }); test("various object property changes", () => { const observer = makeObserver(); const obj: any = { a: 1 }; observer.observe(obj); - expect(obj.__rev__).toBe(0); + expect(obj.__owl__.rev).toBe(1); obj.a = 2; - expect(observer.__rev__).toBe(1); - expect(obj.__rev__).toBe(1); + expect(observer.rev).toBe(2); + expect(obj.__owl__.rev).toBe(2); // same value again obj.a = 2; - expect(observer.__rev__).toBe(1); - expect(obj.__rev__).toBe(1); + expect(observer.rev).toBe(2); + expect(obj.__owl__.rev).toBe(2); obj.a = 3; - expect(observer.__rev__).toBe(2); - expect(obj.__rev__).toBe(2); + expect(observer.rev).toBe(3); + expect(obj.__owl__.rev).toBe(3); }); test("properly observe arrays", () => { const observer = makeObserver(); const arr: any = []; observer.observe(arr); - expect(arr.__rev__).toBe(0); - expect(observer.__rev__).toBe(0); + expect(arr.__owl__.rev).toBe(1); + expect(observer.rev).toBe(1); expect(arr.length).toBe(0); arr.push(1); - expect(arr.__rev__).toBe(1); - expect(observer.__rev__).toBe(1); + expect(arr.__owl__.rev).toBe(2); + expect(observer.rev).toBe(2); expect(arr.length).toBe(1); arr.splice(1, 0, "hey"); - expect(arr.__rev__).toBe(2); - expect(observer.__rev__).toBe(2); + expect(arr.__owl__.rev).toBe(3); + expect(observer.rev).toBe(3); expect(arr.length).toBe(2); arr.unshift("lindemans"); - expect(arr.__rev__).toBe(3); + expect(arr.__owl__.rev).toBe(4); arr.reverse(); - expect(arr.__rev__).toBe(4); + expect(arr.__owl__.rev).toBe(5); arr.pop(); - expect(arr.__rev__).toBe(5); + expect(arr.__owl__.rev).toBe(6); arr.shift(); - expect(arr.__rev__).toBe(6); + expect(arr.__owl__.rev).toBe(7); arr.sort(); - expect(arr.__rev__).toBe(7); + expect(arr.__owl__.rev).toBe(8); expect(arr).toEqual([1]); }); @@ -257,30 +257,30 @@ describe("observer", () => { const observer = makeObserver(); const arr: any = []; observer.observe(arr); - expect(observer.__rev__).toBe(0); + expect(observer.rev).toBe(1); arr.push({ kriek: 5 }); - expect(observer.__rev__).toBe(1); - expect(arr.__rev__).toBe(1); - expect(arr[0].__rev__).toBe(0); + expect(observer.rev).toBe(2); + expect(arr.__owl__.rev).toBe(2); + expect(arr[0].__owl__.rev).toBe(1); arr[0].kriek = 6; - expect(observer.__rev__).toBe(2); - expect(arr.__rev__).toBe(1); - expect(arr[0].__rev__).toBe(1); + expect(observer.rev).toBe(3); + expect(arr.__owl__.rev).toBe(2); + expect(arr[0].__owl__.rev).toBe(2); }); test("properly observe arrays in object", () => { const observer = makeObserver(); const state: any = { arr: [] }; observer.observe(state); - expect(state.arr.__rev__).toBe(0); - expect(observer.__rev__).toBe(0); + expect(state.arr.__owl__.rev).toBe(1); + expect(observer.rev).toBe(1); expect(state.arr.length).toBe(0); state.arr.push(1); - expect(state.arr.__rev__).toBe(1); - expect(observer.__rev__).toBe(1); + expect(state.arr.__owl__.rev).toBe(2); + expect(observer.rev).toBe(2); expect(state.arr.length).toBe(1); }); @@ -288,28 +288,28 @@ describe("observer", () => { const observer = makeObserver(); const state: any = { arr: [{ something: 1 }] }; observer.observe(state); - expect(state.arr.__rev__).toBe(0); - expect(state.arr[0].__rev__).toBe(0); + expect(state.arr.__owl__.rev).toBe(1); + expect(state.arr[0].__owl__.rev).toBe(1); state.arr[0].something = 2; - expect(state.arr.__rev__).toBe(0); - expect(state.arr[0].__rev__).toBe(1); + expect(state.arr.__owl__.rev).toBe(1); + expect(state.arr[0].__owl__.rev).toBe(2); }); test("reobserve new object values", () => { const observer = makeObserver(); const obj: any = { a: 1 }; observer.observe(obj); - expect(obj.__rev__).toBe(0); + expect(obj.__owl__.rev).toBe(1); obj.a = { b: 2 }; - expect(observer.__rev__).toBe(1); - expect(obj.__rev__).toBe(1); - expect(obj.a.__rev__).toBe(0); + expect(observer.rev).toBe(2); + expect(obj.__owl__.rev).toBe(2); + expect(obj.a.__owl__.rev).toBe(1); obj.a.b = 3; - expect(observer.__rev__).toBe(2); - expect(obj.__rev__).toBe(1); - expect(obj.a.__rev__).toBe(1); + expect(observer.rev).toBe(3); + expect(obj.__owl__.rev).toBe(2); + expect(obj.a.__owl__.rev).toBe(2); }); test("properly handle already observed state", () => { @@ -318,17 +318,17 @@ describe("observer", () => { const obj2: any = { b: 1 }; observer.observe(obj1); observer.observe(obj2); - expect(obj1.__rev__).toBe(0); - expect(obj2.__rev__).toBe(0); + expect(obj1.__owl__.rev).toBe(1); + expect(obj2.__owl__.rev).toBe(1); obj1.a = 2; obj2.b = 3; - expect(obj1.__rev__).toBe(1); - expect(obj2.__rev__).toBe(1); + expect(obj1.__owl__.rev).toBe(2); + expect(obj2.__owl__.rev).toBe(2); obj2.b = obj1; - expect(obj1.__rev__).toBe(1); - expect(obj2.__rev__).toBe(2); + expect(obj1.__owl__.rev).toBe(2); + expect(obj2.__owl__.rev).toBe(3); }); test("accept cycles in observed state", () => { @@ -337,12 +337,12 @@ describe("observer", () => { const obj2: any = { b: obj1, key: 1 }; obj1.a = obj2; observer.observe(obj1); - expect(obj1.__rev__).toBe(0); - expect(obj2.__rev__).toBe(0); + expect(obj1.__owl__.rev).toBe(1); + expect(obj2.__owl__.rev).toBe(1); obj2.key = 3; - expect(obj1.__rev__).toBe(0); - expect(obj2.__rev__).toBe(1); + expect(obj1.__owl__.rev).toBe(1); + expect(obj2.__owl__.rev).toBe(2); }); });