[IMP] store: add deep tracking for changes

This is only at the level of the store currently. To be useful, we need
to work on the 'connect' function.
This commit is contained in:
Géry Debongnie
2019-04-14 15:37:27 +02:00
parent 4ea0875fd9
commit f5bbf25d4f
2 changed files with 52 additions and 11 deletions
+19 -11
View File
@@ -137,18 +137,22 @@ export function makeObserver(): Observer {
}
if (newVal !== value) {
value = newVal;
observe(newVal);
observe(newVal, obj);
obj.__owl__.rev!++;
observer.rev++;
let parent = obj;
do {
parent.__owl__.deepRev++;
} while ((parent = parent.__owl__.parent));
}
}
});
observe(value);
observe(value, obj);
}
function observeObj<T extends { __owl__?: any }>(obj: T) {
function observeObj<T extends { __owl__?: any }>(obj: T, parent?: any) {
const keys = Object.keys(obj);
obj.__owl__ = { rev: 1 };
obj.__owl__ = { rev: 1, deepRev: 1, parent };
Object.defineProperty(obj, "__owl__", { enumerable: false });
for (let key of keys) {
addProp(obj, key, obj[key]);
@@ -173,6 +177,10 @@ export function makeObserver(): Observer {
ModifiedArrayProto[method] = function(...args) {
observer.rev++;
this.__owl__.rev++;
let parent = this;
do {
parent.__owl__.deepRev++;
} while ((parent = parent.__owl__.parent));
let inserted;
switch (method) {
case "push":
@@ -185,23 +193,23 @@ export function makeObserver(): Observer {
}
if (inserted) {
for (let elem of inserted) {
observe(elem);
observe(elem, this);
}
}
return initialMethod.call(this, ...args);
};
}
function observeArr(arr: Array<any>) {
(<any>arr).__owl__ = { rev: 1 };
function observeArr(arr: Array<any>, parent?: any) {
(<any>arr).__owl__ = { rev: 1, deepRev: 1, parent };
Object.defineProperty(arr, "__owl__", { enumerable: false });
(<any>arr).__proto__ = ModifiedArrayProto;
for (let i = 0; i < arr.length; i++) {
observe(arr[i]);
observe(arr[i], arr);
}
}
function observe(value: any) {
function observe(value: any, parent?: any) {
if (value === null) {
// fun fact: typeof null === 'object'
return;
@@ -214,9 +222,9 @@ export function makeObserver(): Observer {
return;
}
if (Array.isArray(value)) {
observeArr(value);
observeArr(value, parent);
} else {
observeObj(value);
observeObj(value, parent);
}
}
+33
View File
@@ -296,6 +296,18 @@ describe("observer", () => {
expect(state.arr[0].__owl__.rev).toBe(2);
});
test("properly observe objects in object", () => {
const observer = makeObserver();
const state: any = { a: { b: 1 } };
observer.observe(state);
expect(state.__owl__.rev).toBe(1);
expect(state.a.__owl__.rev).toBe(1);
state.a.b = 2;
expect(state.__owl__.rev).toBe(1);
expect(state.a.__owl__.rev).toBe(2);
});
test("reobserve new object values", () => {
const observer = makeObserver();
const obj: any = { a: 1 };
@@ -312,6 +324,27 @@ describe("observer", () => {
expect(obj.a.__owl__.rev).toBe(2);
});
test("deep observe misc changes", () => {
const observer = makeObserver();
const state: any = { o: { a: 1 }, arr: [1], n: 13 };
observer.observe(state);
expect(state.__owl__.rev).toBe(1);
expect(state.__owl__.deepRev).toBe(1);
state.o.a = 2;
expect(observer.rev).toBe(2);
expect(state.__owl__.rev).toBe(1);
expect(state.__owl__.deepRev).toBe(2);
state.arr.push(2);
expect(state.__owl__.rev).toBe(1);
expect(state.__owl__.deepRev).toBe(3);
state.n = 155;
expect(state.__owl__.rev).toBe(2);
expect(state.__owl__.deepRev).toBe(4);
});
test("properly handle already observed state", () => {
const observer = makeObserver();
const obj1: any = { a: 1 };