diff --git a/src/runtime/lifecycle_hooks.ts b/src/runtime/lifecycle_hooks.ts index 16984ef3..e8ed942d 100644 --- a/src/runtime/lifecycle_hooks.ts +++ b/src/runtime/lifecycle_hooks.ts @@ -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) { diff --git a/tests/components/__snapshots__/error_handling.test.ts.snap b/tests/components/__snapshots__/error_handling.test.ts.snap index bd70be30..f1050afa 100644 --- a/tests/components/__snapshots__/error_handling.test.ts.snap +++ b/tests/components/__snapshots__/error_handling.test.ts.snap @@ -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(\`
abc
\`); + + 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(\`
abc
\`); + + return function template(ctx, node, key = \\"\\") { + return block1(); + } +}" +`; diff --git a/tests/components/error_handling.test.ts b/tests/components/error_handling.test.ts index d1d2aec1..331f10ab 100644 --- a/tests/components/error_handling.test.ts +++ b/tests/components/error_handling.test.ts @@ -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`
abc
`; + 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`
`;