mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[FIX] runtime: don't emit async hook warnings when cancelled/destroyed
Previously, the async hook warning that's emitted when async hooks take too long to resolve would be emitted even if the component was destroyed or cancelled. We used to check if the node's fiber was still the current fiber as a proxy for cancellation, but this is insufficient in the case where an app might be destroyed. This commit also wraps the content of some of the warning tests into a try/finally block so that a failure of these tests doesn't pollute setTimeout and console.warn and cause other tests to timeout one after another.
This commit is contained in:
committed by
Géry Debongnie
parent
e6c3b62ef0
commit
fddb1ec924
@@ -28,7 +28,7 @@ function wrapError(fn: (...args: any[]) => any, hookName: string) {
|
|||||||
result.catch(() => {}),
|
result.catch(() => {}),
|
||||||
new Promise((resolve) => setTimeout(() => resolve(TIMEOUT), 3000)),
|
new Promise((resolve) => setTimeout(() => resolve(TIMEOUT), 3000)),
|
||||||
]).then((res) => {
|
]).then((res) => {
|
||||||
if (res === TIMEOUT && node.fiber === fiber) {
|
if (res === TIMEOUT && node.fiber === fiber && node.status <= 2) {
|
||||||
console.warn(timeoutError);
|
console.warn(timeoutError);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -683,6 +683,19 @@ exports[`lifecycle hooks sub widget (inside sub node): hooks are correctly calle
|
|||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`lifecycle hooks timeout in onWillStart doesn't emit a warning if app is destroyed 1`] = `
|
||||||
|
"function anonymous(app, bdom, helpers
|
||||||
|
) {
|
||||||
|
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
|
||||||
|
|
||||||
|
let block1 = createBlock(\`<span/>\`);
|
||||||
|
|
||||||
|
return function template(ctx, node, key = \\"\\") {
|
||||||
|
return block1();
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`lifecycle hooks timeout in onWillStart emits a warning 1`] = `
|
exports[`lifecycle hooks timeout in onWillStart emits a warning 1`] = `
|
||||||
"function anonymous(app, bdom, helpers
|
"function anonymous(app, bdom, helpers
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
import { App, Component, mount, onMounted, onWillStart, useState, xml } from "../../src";
|
|
||||||
import {
|
import {
|
||||||
|
App,
|
||||||
|
Component,
|
||||||
|
mount,
|
||||||
|
useState,
|
||||||
|
xml,
|
||||||
onWillPatch,
|
onWillPatch,
|
||||||
onWillUnmount,
|
onWillUnmount,
|
||||||
onPatched,
|
onPatched,
|
||||||
@@ -7,7 +11,9 @@ import {
|
|||||||
onWillRender,
|
onWillRender,
|
||||||
onWillDestroy,
|
onWillDestroy,
|
||||||
onRendered,
|
onRendered,
|
||||||
} from "../../src/runtime/lifecycle_hooks";
|
onMounted,
|
||||||
|
onWillStart,
|
||||||
|
} from "../../src";
|
||||||
import { status } from "../../src/runtime/status";
|
import { status } from "../../src/runtime/status";
|
||||||
import {
|
import {
|
||||||
elem,
|
elem,
|
||||||
@@ -117,6 +123,7 @@ describe("lifecycle hooks", () => {
|
|||||||
timeoutCbs[++timeoutId] = cb;
|
timeoutCbs[++timeoutId] = cb;
|
||||||
return timeoutId;
|
return timeoutId;
|
||||||
}) as any;
|
}) as any;
|
||||||
|
try {
|
||||||
class Test extends Component {
|
class Test extends Component {
|
||||||
static template = xml`<span/>`;
|
static template = xml`<span/>`;
|
||||||
setup() {
|
setup() {
|
||||||
@@ -133,8 +140,43 @@ describe("lifecycle hooks", () => {
|
|||||||
await nextMicroTick();
|
await nextMicroTick();
|
||||||
expect(console.warn).toHaveBeenCalledTimes(1);
|
expect(console.warn).toHaveBeenCalledTimes(1);
|
||||||
expect(warnArgs![0]!.message).toBe("onWillStart's promise hasn't resolved after 3 seconds");
|
expect(warnArgs![0]!.message).toBe("onWillStart's promise hasn't resolved after 3 seconds");
|
||||||
|
} finally {
|
||||||
console.warn = warn;
|
console.warn = warn;
|
||||||
window.setTimeout = setTimeout;
|
window.setTimeout = setTimeout;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test("timeout in onWillStart doesn't emit a warning if app is destroyed", async () => {
|
||||||
|
const { warn } = console;
|
||||||
|
console.warn = jest.fn();
|
||||||
|
const { setTimeout } = window;
|
||||||
|
let timeoutCbs: any = {};
|
||||||
|
let timeoutId = 0;
|
||||||
|
window.setTimeout = ((cb: any) => {
|
||||||
|
timeoutCbs[++timeoutId] = cb;
|
||||||
|
return timeoutId;
|
||||||
|
}) as any;
|
||||||
|
try {
|
||||||
|
class Test extends Component {
|
||||||
|
static template = xml`<span/>`;
|
||||||
|
setup() {
|
||||||
|
onWillStart(() => new Promise(() => {}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const app = new App(Test, { test: true });
|
||||||
|
app.mount(fixture);
|
||||||
|
app.destroy();
|
||||||
|
for (const id in timeoutCbs) {
|
||||||
|
timeoutCbs[id]();
|
||||||
|
delete timeoutCbs[id];
|
||||||
|
}
|
||||||
|
await nextMicroTick();
|
||||||
|
await nextMicroTick();
|
||||||
|
expect(console.warn).toHaveBeenCalledTimes(0);
|
||||||
|
} finally {
|
||||||
|
console.warn = warn;
|
||||||
|
window.setTimeout = setTimeout;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test("timeout in onWillUpdateProps emits a warning", async () => {
|
test("timeout in onWillUpdateProps emits a warning", async () => {
|
||||||
@@ -162,6 +204,7 @@ describe("lifecycle hooks", () => {
|
|||||||
return timeoutId;
|
return timeoutId;
|
||||||
}) as any;
|
}) as any;
|
||||||
|
|
||||||
|
try {
|
||||||
parent.state.prop = 2;
|
parent.state.prop = 2;
|
||||||
let tick = nextTick();
|
let tick = nextTick();
|
||||||
for (const id in timeoutCbs) {
|
for (const id in timeoutCbs) {
|
||||||
@@ -179,8 +222,10 @@ describe("lifecycle hooks", () => {
|
|||||||
expect(warnArgs![0]!.message).toBe(
|
expect(warnArgs![0]!.message).toBe(
|
||||||
"onWillUpdateProps's promise hasn't resolved after 3 seconds"
|
"onWillUpdateProps's promise hasn't resolved after 3 seconds"
|
||||||
);
|
);
|
||||||
|
} finally {
|
||||||
console.warn = warn;
|
console.warn = warn;
|
||||||
window.setTimeout = setTimeout;
|
window.setTimeout = setTimeout;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test("mounted hook is called if mounted in DOM", async () => {
|
test("mounted hook is called if mounted in DOM", async () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user