diff --git a/src/runtime/error_handling.ts b/src/runtime/error_handling.ts index 275e138b..e264eb84 100644 --- a/src/runtime/error_handling.ts +++ b/src/runtime/error_handling.ts @@ -55,6 +55,7 @@ export function handleError(params: ErrorParams) { let current: Fiber | null = fiber; do { current.node.fiber = current; + fibersInError.set(current, error); current = current.parent; } while (current); diff --git a/tests/components/__snapshots__/error_handling.test.ts.snap b/tests/components/__snapshots__/error_handling.test.ts.snap index 20ff0046..acacbeb0 100644 --- a/tests/components/__snapshots__/error_handling.test.ts.snap +++ b/tests/components/__snapshots__/error_handling.test.ts.snap @@ -94,6 +94,52 @@ exports[`basics no component catching error lead to full app destruction 2`] = ` }" `; +exports[`basics render from above on error -- handler is not a Root or MountFiber 1`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + const comp1 = app.createComponent(\`Parent\`, true, false, false, []); + + return function template(ctx, node, key = \\"\\") { + return comp1({}, key + \`__1\`, node, this, null); + } +}" +`; + +exports[`basics render from above on error -- handler is not a Root or MountFiber 2`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + const comp1 = app.createComponent(\`Boom\`, true, false, false, []); + + let block1 = createBlock(\`
\`); + + return function template(ctx, node, key = \\"\\") { + let b2, b3; + if (ctx['error']) { + b2 = text(\`Error\`); + } else { + b3 = comp1({onError: (ctx['handleError']).bind(this)}, key + \`__1\`, node, this, null); + } + return block1([], [b2, b3]); + } +}" +`; + +exports[`basics render from above on error -- handler is not a Root or MountFiber 3`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + + let block1 = createBlock(\`
\`); + + return function template(ctx, node, key = \\"\\") { + let txt1 = ctx['a'].b.c; + return block1([txt1]); + } +}" +`; + exports[`basics simple catchError 1`] = ` "function anonymous(app, bdom, helpers ) { diff --git a/tests/components/error_handling.test.ts b/tests/components/error_handling.test.ts index 67254427..7b512b2b 100644 --- a/tests/components/error_handling.test.ts +++ b/tests/components/error_handling.test.ts @@ -233,6 +233,44 @@ function(app, bdom, helpers) { expect(mockConsoleError).toBeCalledTimes(0); expect(mockConsoleWarn).toBeCalledTimes(0); }); + + test("render from above on error -- handler is not a Root or MountFiber", async () => { + class Boom extends Component { + static template = xml`
`; + setup() { + onError((err) => { + this.props.onError(err); + }); + } + } + + class Parent extends Component { + static template = xml` +
+ Error + + + +
`; + static components = { Boom }; + + error: any = false; + + handleError(err: Error) { + this.error = err; + this.render(); + } + } + + class GrandParent extends Component { + static template: string = xml``; + static components = { Parent }; + } + await mount(GrandParent, fixture); + expect(fixture.innerHTML).toBe("
Error
"); + expect(mockConsoleError).toBeCalledTimes(0); + expect(mockConsoleWarn).toBeCalledTimes(0); + }); }); describe("errors and promises", () => {