[FIX] lifecyle_hooks: correctly wrap errors in async code

Before this commit, wrapping an error occurring in async code
would result in an unhandledpromise exception, because we created
another promise, that would be rejected and that we didn't catch.
This commit is contained in:
Aaron Bohy
2022-07-15 16:04:19 +02:00
committed by Géry Debongnie
parent d1118455aa
commit 30bc605c84
3 changed files with 51 additions and 1 deletions
+1 -1
View File
@@ -15,7 +15,7 @@ function wrapError(fn: (...args: any[]) => any, hookName: string) {
if (hookName === "onWillStart" || hookName === "onWillUpdateProps") {
const fiber = node.fiber;
Promise.race([
result,
result.catch(() => {}),
new Promise((resolve) => setTimeout(() => resolve(TIMEOUT), 3000)),
]).then((res) => {
if (res === TIMEOUT && node.fiber === fiber) {
@@ -1257,6 +1257,19 @@ exports[`errors and promises an error in willPatch call will reject the render p
}"
`;
exports[`errors and promises error type is kept when it is wrapped 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<div>abc</div>\`);
return function template(ctx, node, key = \\"\\") {
return block1();
}
}"
`;
exports[`errors and promises errors in mounted and in willUnmount 1`] = `
"function anonymous(app, bdom, helpers
) {
@@ -1296,3 +1309,16 @@ exports[`errors and promises errors in rerender 1`] = `
}
}"
`;
exports[`errors and promises wrapped errors in async code are correctly caught 1`] = `
"function anonymous(app, bdom, helpers
) {
let { text, createBlock, list, multi, html, toggler, comment } = bdom;
let block1 = createBlock(\`<div>abc</div>\`);
return function template(ctx, node, key = \\"\\") {
return block1();
}
}"
`;
+24
View File
@@ -264,6 +264,30 @@ describe("errors and promises", () => {
expect(error!.message).toBe("Tokenizer error: could not tokenize `{ 'invalid: 5 }`");
});
test("wrapped errors in async code are correctly caught", async () => {
class Root extends Component {
static template = xml`<div>abc</div>`;
setup() {
onWillStart(async () => {
await Promise.resolve();
throw new Error("boom in onWillStart");
});
}
}
let error: any;
try {
await mount(Root, fixture, { test: true });
} catch (e) {
error = e;
}
expect(error!).toBeDefined();
expect(error!.message).toBe(
`The following error occurred in onWillStart: "boom in onWillStart"`
);
await new Promise((r) => setTimeout(r, 0)); // wait for the rejection event to bubble
});
test("an error in willPatch call will reject the render promise", async () => {
class Root extends Component {
static template = xml`<div><t t-esc="val"/></div>`;