[FIX] observer: does not proxify promises

Promises are kind of special, and do not behave like usual javascript
values.

For this issue, the problem is that when the observer tries to observe a
promise value, the code will crash with an error like this:

Uncaught TypeError: Method Promise.prototype.then called on incompatible receiver [object Object]

Also, note that it does not make much sense to proxify promise methods
anyway, since they are not (supposed) to be modified.

So, with this commit, we simply consider that promises should be treated
like a primitive value: simply ignored when determining if it should be
proxified

Note that I actually believe that putting promises in a useState is not
a good idea in general.

closes #677
This commit is contained in:
Géry Debongnie
2020-09-17 10:52:20 +02:00
committed by aab-odoo
parent 7b8ac13d3f
commit b2db7f21ed
3 changed files with 24 additions and 2 deletions
+6 -1
View File
@@ -25,7 +25,12 @@ export class Observer {
notifyCB() {}
observe<T>(value: T, parent?: any): T {
if (value === null || typeof value !== "object" || value instanceof Date) {
if (
value === null ||
typeof value !== "object" ||
value instanceof Date ||
value instanceof Promise
) {
// fun fact: typeof null === 'object'
return value;
}
+1 -1
View File
@@ -86,7 +86,7 @@ interface Utils {
[key: string]: any;
}
function isComponent(obj) {
function isComponent(obj): boolean {
return obj && obj.hasOwnProperty("__owl__");
}
+17
View File
@@ -68,6 +68,23 @@ describe("observer", () => {
expect(obj.date).not.toBe(date);
});
test("properly handle promises (i.e.: treat them like primitive values", async () => {
const observer = new Observer();
let resolved = false;
const prom = new Promise((r) => r());
const obj: any = observer.observe({ prom });
expect(obj.prom).toBeInstanceOf(Promise);
obj.prom.then(() => (resolved = true));
expect(observer.revNumber(obj)).toBe(1);
expect(resolved).toBe(false);
await Promise.resolve();
expect(resolved).toBe(true);
expect(observer.revNumber(obj)).toBe(1);
});
test("can change values in array", () => {
const observer = new Observer();
const obj: any = observer.observe({ arr: [1, 2] });