From: edison Date: Tue, 25 Nov 2025 05:49:24 +0000 (+0800) Subject: fix(compiler-vapor): only apply v-on key modifiers to keyboard events (#14136) X-Git-Tag: v3.6.0-alpha.6~42 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8e83197bc7068b8217af92de41ed3fd920e91b80;p=thirdparty%2Fvuejs%2Fcore.git fix(compiler-vapor): only apply v-on key modifiers to keyboard events (#14136) --- diff --git a/packages/compiler-dom/src/index.ts b/packages/compiler-dom/src/index.ts index 446a917ad7..5a93004c69 100644 --- a/packages/compiler-dom/src/index.ts +++ b/packages/compiler-dom/src/index.ts @@ -74,7 +74,7 @@ export { DOMErrorCodes, DOMErrorMessages, } from './errors' -export { resolveModifiers } from './transforms/vOn' +export { resolveModifiers, isKeyboardEvent } from './transforms/vOn' export { isValidHTMLNesting } from './htmlNesting' export { postTransformTransition } from './transforms/Transition' export * from '@vue/compiler-core' diff --git a/packages/compiler-dom/src/transforms/vOn.ts b/packages/compiler-dom/src/transforms/vOn.ts index 723229cf34..136ec842a2 100644 --- a/packages/compiler-dom/src/transforms/vOn.ts +++ b/packages/compiler-dom/src/transforms/vOn.ts @@ -28,7 +28,9 @@ const isNonKeyModifier = /*@__PURE__*/ makeMap( ) // left & right could be mouse or key modifiers based on event type const maybeKeyModifier = /*@__PURE__*/ makeMap('left,right') -const isKeyboardEvent = /*@__PURE__*/ makeMap(`onkeyup,onkeydown,onkeypress`) +export const isKeyboardEvent: (key: string) => boolean = /*@__PURE__*/ makeMap( + `onkeyup,onkeydown,onkeypress`, +) export const resolveModifiers = ( key: ExpressionNode | string, diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformElement.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformElement.spec.ts.snap index 69ce4b9b28..dd2d4abb24 100644 --- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformElement.spec.ts.snap +++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformElement.spec.ts.snap @@ -278,11 +278,11 @@ export function render(_ctx) { `; exports[`compiler: element transform > component event with multiple modifiers and event options 1`] = ` -"import { resolveComponent as _resolveComponent, withModifiers as _withModifiers, withKeys as _withKeys, createComponentWithFallback as _createComponentWithFallback } from 'vue'; +"import { resolveComponent as _resolveComponent, withModifiers as _withModifiers, createComponentWithFallback as _createComponentWithFallback } from 'vue'; export function render(_ctx) { const _component_Foo = _resolveComponent("Foo") - const n0 = _createComponentWithFallback(_component_Foo, { onFooCaptureOnce: () => _withKeys(_withModifiers(_ctx.bar, ["stop","prevent"]), ["enter"]) }, null, true) + const n0 = _createComponentWithFallback(_component_Foo, { onFooCaptureOnce: () => _withModifiers(_ctx.bar, ["stop","prevent"]) }, null, true) return n0 }" `; @@ -434,14 +434,14 @@ export function render(_ctx) { `; exports[`compiler: element transform > props merging: event handlers 1`] = ` -"import { createInvoker as _createInvoker, withKeys as _withKeys, delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue'; +"import { createInvoker as _createInvoker, delegate as _delegate, delegateEvents as _delegateEvents, template as _template } from 'vue'; const t0 = _template("
", true) _delegateEvents("click") export function render(_ctx) { const n0 = t0() - _delegate(n0, "click", _createInvoker(_withKeys(e => _ctx.a(e), ["foo"]))) - _delegate(n0, "click", _createInvoker(_withKeys(e => _ctx.b(e), ["bar"]))) + _delegate(n0, "click", _createInvoker(e => _ctx.a(e))) + _delegate(n0, "click", _createInvoker(e => _ctx.b(e))) return n0 }" `; diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOn.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOn.spec.ts.snap index dece57bcf3..ec68982edf 100644 --- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOn.spec.ts.snap +++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOn.spec.ts.snap @@ -122,7 +122,7 @@ export function render(_ctx, $props, $emit, $attrs, $slots) { n7.$evtcontextmenu = _createInvoker(_withModifiers(_ctx.handleEvent, ["right"])) n8.$evtclick = _createInvoker(_withModifiers(_ctx.handleEvent, ["left"])) n9.$evtmouseup = _createInvoker(_withModifiers(_ctx.handleEvent, ["middle"])) - n10.$evtcontextmenu = _createInvoker(_withKeys(_withModifiers(_ctx.handleEvent, ["right"]), ["enter"])) + n10.$evtcontextmenu = _createInvoker(_withModifiers(_ctx.handleEvent, ["right"])) n11.$evtkeyup = _createInvoker(_withKeys(_ctx.handleEvent, ["enter"])) n12.$evtkeyup = _createInvoker(_withKeys(_ctx.handleEvent, ["tab"])) n13.$evtkeyup = _createInvoker(_withKeys(_ctx.handleEvent, ["delete"])) diff --git a/packages/compiler-vapor/__tests__/transforms/transformElement.spec.ts b/packages/compiler-vapor/__tests__/transforms/transformElement.spec.ts index ffedee627f..26a8ee06ba 100644 --- a/packages/compiler-vapor/__tests__/transforms/transformElement.spec.ts +++ b/packages/compiler-vapor/__tests__/transforms/transformElement.spec.ts @@ -963,7 +963,7 @@ describe('compiler: element transform', () => { key: { content: 'foo' }, handler: true, handlerModifiers: { - keys: ['enter'], + keys: [], nonKeys: ['stop', 'prevent'], options: ['capture', 'once'], }, diff --git a/packages/compiler-vapor/src/transforms/vOn.ts b/packages/compiler-vapor/src/transforms/vOn.ts index fe63ece0a8..aa0662e9ca 100644 --- a/packages/compiler-vapor/src/transforms/vOn.ts +++ b/packages/compiler-vapor/src/transforms/vOn.ts @@ -2,6 +2,8 @@ import { ElementTypes, ErrorCodes, createCompilerError, + isKeyboardEvent, + isStaticExp, } from '@vue/compiler-dom' import type { DirectiveTransform } from '../transform' import { IRNodeTypes, type KeyOverride, type SetEventIRNode } from '../ir' @@ -59,6 +61,16 @@ export const transformVOn: DirectiveTransform = (dir, node, context) => { } } + // don't gen keys guard for non-keyboard events + // if event name is dynamic, always wrap with keys guard + if ( + keyModifiers.length && + isStaticExp(arg) && + !isKeyboardEvent(`on${arg.content.toLowerCase()}`) + ) { + keyModifiers.length = 0 + } + if (isComponent || isSlotOutlet) { const handler = exp || EMPTY_EXPRESSION return {