diff --git a/src/component/handler.ts b/src/component/handler.ts index 57af331f..35aece9d 100644 --- a/src/component/handler.ts +++ b/src/component/handler.ts @@ -31,9 +31,13 @@ export const mainEventHandler = (data: any, ev: Event, currentTarget?: EventTarg // We check this rather than data[0] being truthy (or typeof function) so that it crashes // as expected when there is a handler expression that evaluates to a falsy value if (Object.hasOwnProperty.call(data, 0)) { + const handler = data[0]; + if (typeof handler !== "function") { + throw new Error(`Invalid handler (expected a function, received: '${handler}')`); + } let node = data[1] ? data[1].__owl__ : null; if (node ? node.status === STATUS.MOUNTED : true) { - data[0].call(node ? node.component : null, ev); + handler.call(node ? node.component : null, ev); } } return stopped; diff --git a/tests/components/__snapshots__/event_handling.test.ts.snap b/tests/components/__snapshots__/event_handling.test.ts.snap index 47e73ccf..d6b4e7be 100644 --- a/tests/components/__snapshots__/event_handling.test.ts.snap +++ b/tests/components/__snapshots__/event_handling.test.ts.snap @@ -1,5 +1,19 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`event handling Invalid handler throws an error 1`] = ` +"function anonymous(bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, component, comment } = bdom; + + let block1 = createBlock(\`\`); + + return function template(ctx, node, key = \\"\\") { + let hdlr1 = [ctx['dosomething'], ctx]; + return block1([hdlr1]); + } +}" +`; + exports[`event handling handler is not called if component is destroyed 1`] = ` "function anonymous(bdom, helpers ) { diff --git a/tests/components/event_handling.test.ts b/tests/components/event_handling.test.ts index 2134184a..1e18e47d 100644 --- a/tests/components/event_handling.test.ts +++ b/tests/components/event_handling.test.ts @@ -33,6 +33,28 @@ describe("event handling", () => { expect(fixture.innerHTML).toBe("
simple vnode
2
"); }); + test("Invalid handler throws an error", async () => { + window.addEventListener( + "error", + (ev) => { + logStep(ev.error.message); + ev.preventDefault(); + }, + { once: true } + ); + + class Parent extends Component { + static template = xml``; + + doSomething() {} + } + + await mount(Parent, fixture); + expect([]).toBeLogged(); + fixture.querySelector("button")!.click(); + expect(["Invalid handler (expected a function, received: 'undefined')"]).toBeLogged(); + }); + test("support for callable expression in event handler", async () => { class Counter extends Component { static template = xml`