From 8fe4c0c76eebaf6f6061153eada7c0ea1d2446f9 Mon Sep 17 00:00:00 2001 From: Samuel Degueldre Date: Tue, 6 Sep 2022 11:56:58 +0200 Subject: [PATCH] [FIX] events: correctly call handlers in iframes Previously, event handlers would not work when an app was mounted in an iframe, this is caused by a guard in the event handler that checks that the target element is still in the document, but it doesn't check against the correct document in the case of an iframe. This commit changes the check to check against the target's ownerDocument. --- src/runtime/blockdom/events.ts | 4 ++-- .../__snapshots__/event_handling.test.ts.snap | 14 ++++++++++++++ tests/components/event_handling.test.ts | 18 ++++++++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/runtime/blockdom/events.ts b/src/runtime/blockdom/events.ts index f4bdfe60..f2b3b474 100644 --- a/src/runtime/blockdom/events.ts +++ b/src/runtime/blockdom/events.ts @@ -27,8 +27,8 @@ function createElementHandler(evName: string, capture: boolean = false): EventHa } function listener(ev: Event) { - const currentTarget = ev.currentTarget; - if (!currentTarget || !document.contains(currentTarget as HTMLElement)) return; + const currentTarget = ev.currentTarget as HTMLElement; + if (!currentTarget || !currentTarget.ownerDocument.contains(currentTarget)) return; const data = (currentTarget as any)[eventKey]; if (!data) return; config.mainEventHandler(data, ev, currentTarget); diff --git a/tests/components/__snapshots__/event_handling.test.ts.snap b/tests/components/__snapshots__/event_handling.test.ts.snap index 579a1a49..d111aadc 100644 --- a/tests/components/__snapshots__/event_handling.test.ts.snap +++ b/tests/components/__snapshots__/event_handling.test.ts.snap @@ -58,6 +58,20 @@ exports[`event handling handler receive the event as argument 2`] = ` }" `; +exports[`event handling handler works when app is mounted in an iframe 1`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + + let block1 = createBlock(\`click me\`); + + return function template(ctx, node, key = \\"\\") { + let hdlr1 = [ctx['inc'], ctx]; + return block1([hdlr1]); + } +}" +`; + exports[`event handling input blur event is not called if component is destroyed 1`] = ` "function anonymous(app, bdom, helpers ) { diff --git a/tests/components/event_handling.test.ts b/tests/components/event_handling.test.ts index 1e18e47d..a15ceadc 100644 --- a/tests/components/event_handling.test.ts +++ b/tests/components/event_handling.test.ts @@ -171,4 +171,22 @@ describe("event handling", () => { // input is removed when component is destroyed => nothing should happen expect([]).toBeLogged(); }); + + test("handler works when app is mounted in an iframe", async () => { + let clickCount = 0; + + class Parent extends Component { + static template = xml`click me`; + inc() { + clickCount++; + } + } + const iframe = document.createElement("iframe"); + fixture.appendChild(iframe); + const iframeDoc = iframe.contentDocument!; + await mount(Parent, iframeDoc.body); + expect(clickCount).toBe(0); + iframeDoc.querySelector("span")!.click(); + expect(clickCount).toBe(1); + }); });