From 31fce0926c89480d27733ed7e0106ecec108eb5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Debongnie?= Date: Wed, 1 Jun 2022 07:47:45 +0200 Subject: [PATCH] [FIX] event: no crash when using t-on + modifier on slots/components closes #1185 --- src/runtime/blockdom/event_catcher.ts | 7 ++- .../__snapshots__/t_on.test.ts.snap | 60 +++++++++++++++++++ tests/components/t_on.test.ts | 46 +++++++++++++- 3 files changed, 110 insertions(+), 3 deletions(-) diff --git a/src/runtime/blockdom/event_catcher.ts b/src/runtime/blockdom/event_catcher.ts index c888a971..1f54ae12 100644 --- a/src/runtime/blockdom/event_catcher.ts +++ b/src/runtime/blockdom/event_catcher.ts @@ -33,9 +33,12 @@ export function createCatcher(eventsSpec: EventsSpec): Catcher { this.afterNode = afterNode; this.child.mount(parent, afterNode); for (let i = 0; i < n; i++) { - let origFn = this.handlers[i][0]; + let handler = this.handlers[i]; + // handler = [...mods, fn, comp], so we need to replace second to last elem + let idx = handler.length - 2; + let origFn = handler[idx]; const self = this; - this.handlers[i][0] = function (ev: any) { + handler[idx] = function (ev: any) { const target = ev.target; let currentNode: any = self.child.firstNode(); const afterNode = self.afterNode; diff --git a/tests/components/__snapshots__/t_on.test.ts.snap b/tests/components/__snapshots__/t_on.test.ts.snap index 02391709..a0f8f501 100644 --- a/tests/components/__snapshots__/t_on.test.ts.snap +++ b/tests/components/__snapshots__/t_on.test.ts.snap @@ -212,6 +212,34 @@ exports[`t-on t-on on components, variation 2`] = ` }" `; +exports[`t-on t-on on components, with 'prevent' modifier 1`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, component, comment } = bdom; + let { createCatcher } = helpers; + const catcher1 = createCatcher({\\"click.prevent\\":0}); + + return function template(ctx, node, key = \\"\\") { + const hdlr1 = [\\"prevent\\", ctx['increment'], ctx]; + return catcher1(component(\`Child\`, {value: ctx['state'].value}, key + \`__1\`, node, ctx), [hdlr1]); + } +}" +`; + +exports[`t-on t-on on components, with 'prevent' modifier 2`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, component, comment } = bdom; + + let block1 = createBlock(\`\`); + + return function template(ctx, node, key = \\"\\") { + let txt1 = ctx['props'].value; + return block1([txt1]); + } +}" +`; + exports[`t-on t-on on destroyed components 1`] = ` "function anonymous(app, bdom, helpers ) { @@ -243,6 +271,38 @@ exports[`t-on t-on on destroyed components 2`] = ` }" `; +exports[`t-on t-on on slot, with 'prevent' modifier 1`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, component, comment } = bdom; + let { markRaw } = helpers; + + let block1 = createBlock(\`\`); + + function slot1(ctx, node, key = \\"\\") { + return block1(); + } + + return function template(ctx, node, key = \\"\\") { + return component(\`Child\`, {slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, ctx); + } +}" +`; + +exports[`t-on t-on on slot, with 'prevent' modifier 2`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, component, comment } = bdom; + let { callSlot, createCatcher } = helpers; + const catcher1 = createCatcher({\\"click.prevent\\":0}); + + return function template(ctx, node, key = \\"\\") { + const hdlr1 = [\\"prevent\\", ctx['doSomething'], ctx]; + return catcher1(callSlot(ctx, node, key, 'default', false, null), [hdlr1]); + } +}" +`; + exports[`t-on t-on on t-set-slots 1`] = ` "function anonymous(app, bdom, helpers ) { diff --git a/tests/components/t_on.test.ts b/tests/components/t_on.test.ts index 7d692e53..43b7ff33 100644 --- a/tests/components/t_on.test.ts +++ b/tests/components/t_on.test.ts @@ -1,5 +1,5 @@ import { Component, mount, onMounted, useState, xml } from "../../src/index"; -import { elem, makeTestFixture, nextTick, snapshotEverything } from "../helpers"; +import { elem, logStep, makeTestFixture, nextTick, snapshotEverything } from "../helpers"; import { status } from "../../src/runtime/status"; snapshotEverything(); @@ -275,4 +275,48 @@ describe("t-on", () => { await nextTick(); expect(fixture.innerHTML).toBe(" [1]

something

paragraph

"); }); + + test("t-on on components, with 'prevent' modifier", async () => { + expect.assertions(4); // 2 snaps and 2 expects + class Child extends Component { + static template = xml`"); + }); + + test("t-on on slot, with 'prevent' modifier", async () => { + class Child extends Component { + static template = xml``; + doSomething(ev: MouseEvent) { + expect(ev.defaultPrevented).toBe(true); + logStep("hey"); + } + } + + class Parent extends Component { + static template = xml` + + + `; + static components = { Child }; + } + await mount(Parent, fixture); + fixture.querySelector("button")!.click(); + await nextTick(); + expect(fixture.innerHTML).toBe(""); + expect(["hey"]).toBeLogged(); + }); });