diff --git a/src/store.ts b/src/store.ts index e4a1409d..38fedb61 100644 --- a/src/store.ts +++ b/src/store.ts @@ -158,17 +158,40 @@ export function makeObserver(): Observer { const ArrayProto = Array.prototype; const ModifiedArrayProto = Object.create(ArrayProto); - ModifiedArrayProto.push = function(...args) { - observer.__rev__++; - this.__rev__++; - return ArrayProto.push.call(this, ...args); - }; + const methodsToPatch = [ + "push", + "pop", + "shift", + "unshift", + "splice", + "sort", + "reverse" + ]; + + for (let method of methodsToPatch) { + const initialMethod = ArrayProto[method]; + ModifiedArrayProto[method] = function(...args) { + observer.__rev__++; + this.__rev__++; + let inserted; + switch (method) { + case "push": + case "unshift": + inserted = args; + break; + case "splice": + inserted = args.slice(2); + break; + } + if (inserted) { + for (let elem of inserted) { + observe(elem); + } + } + return initialMethod.call(this, ...args); + }; + } - ModifiedArrayProto.pop = function(...args) { - observer.__rev__++; - this.__rev__++; - return ArrayProto.pop.call(this, ...args); - }; function observeArr(arr: Array) { (arr).__rev__ = 0; Object.defineProperty(arr, "__rev__", { enumerable: false }); diff --git a/tests/store.test.ts b/tests/store.test.ts index b58f73e5..cbd9ac7c 100644 --- a/tests/store.test.ts +++ b/tests/store.test.ts @@ -210,6 +210,45 @@ describe("observer", () => { expect(arr.__rev__).toBe(1); expect(observer.__rev__).toBe(1); expect(arr.length).toBe(1); + + arr.splice(1, 0, "hey"); + expect(arr.__rev__).toBe(2); + expect(observer.__rev__).toBe(2); + expect(arr.length).toBe(2); + + arr.unshift("lindemans"); + expect(arr.__rev__).toBe(3); + + arr.reverse(); + expect(arr.__rev__).toBe(4); + + arr.pop(); + expect(arr.__rev__).toBe(5); + + arr.shift(); + expect(arr.__rev__).toBe(6); + + arr.sort(); + expect(arr.__rev__).toBe(7); + + expect(arr).toEqual([1]); + }); + + test("object pushed into arrays are observed", () => { + const observer = makeObserver(); + const arr: any = []; + observer.observe(arr); + expect(observer.__rev__).toBe(0); + + arr.push({ kriek: 5 }); + expect(observer.__rev__).toBe(1); + expect(arr.__rev__).toBe(1); + expect(arr[0].__rev__).toBe(0); + + arr[0].kriek = 6; + expect(observer.__rev__).toBe(2); + expect(arr.__rev__).toBe(1); + expect(arr[0].__rev__).toBe(1); }); test("properly observe arrays in object", () => {