From f0705607414ebda4d28de823e6a5cbad0302db20 Mon Sep 17 00:00:00 2001 From: linzhe141 <1572213544@qq.com> Date: Tue, 18 Mar 2025 11:27:53 +0800 Subject: [PATCH 1/4] fix: handle nullish dynamic event name with a modifier --- packages/compiler-core/src/runtimeHelpers.ts | 4 ++++ packages/compiler-dom/src/transforms/vOn.ts | 7 ++++++- packages/runtime-core/src/helpers/toHandlers.ts | 8 ++++++++ packages/runtime-core/src/index.ts | 2 +- 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/packages/compiler-core/src/runtimeHelpers.ts b/packages/compiler-core/src/runtimeHelpers.ts index 7cf3757b2..05684f7ef 100644 --- a/packages/compiler-core/src/runtimeHelpers.ts +++ b/packages/compiler-core/src/runtimeHelpers.ts @@ -63,6 +63,9 @@ export const CAPITALIZE: unique symbol = Symbol(__DEV__ ? `capitalize` : ``) export const TO_HANDLER_KEY: unique symbol = Symbol( __DEV__ ? `toHandlerKey` : ``, ) +export const CHECK_DYNAMIC_EVENT: unique symbol = Symbol( + __DEV__ ? `checkDynamicEvent` : ``, +) export const SET_BLOCK_TRACKING: unique symbol = Symbol( __DEV__ ? `setBlockTracking` : ``, ) @@ -115,6 +118,7 @@ export const helperNameMap: Record = { [CAMELIZE]: `camelize`, [CAPITALIZE]: `capitalize`, [TO_HANDLER_KEY]: `toHandlerKey`, + [CHECK_DYNAMIC_EVENT]: `checkDynamicEvent`, [SET_BLOCK_TRACKING]: `setBlockTracking`, [PUSH_SCOPE_ID]: `pushScopeId`, [POP_SCOPE_ID]: `popScopeId`, diff --git a/packages/compiler-dom/src/transforms/vOn.ts b/packages/compiler-dom/src/transforms/vOn.ts index 1bb576318..d4fac6830 100644 --- a/packages/compiler-dom/src/transforms/vOn.ts +++ b/packages/compiler-dom/src/transforms/vOn.ts @@ -1,4 +1,5 @@ import { + CHECK_DYNAMIC_EVENT, CompilerDeprecationTypes, type DirectiveTransform, type ExpressionNode, @@ -144,7 +145,11 @@ export const transformOn: DirectiveTransform = (dir, node, context) => { const modifierPostfix = eventOptionModifiers.map(capitalize).join('') key = isStaticExp(key) ? createSimpleExpression(`${key.content}${modifierPostfix}`, true) - : createCompoundExpression([`(`, key, `) + "${modifierPostfix}"`]) + : createCompoundExpression([ + `${context.helperString(CHECK_DYNAMIC_EVENT)}(`, + key, + `,"${modifierPostfix}")`, + ]) } return { diff --git a/packages/runtime-core/src/helpers/toHandlers.ts b/packages/runtime-core/src/helpers/toHandlers.ts index 3e7dcb327..6d2339d6a 100644 --- a/packages/runtime-core/src/helpers/toHandlers.ts +++ b/packages/runtime-core/src/helpers/toHandlers.ts @@ -23,3 +23,11 @@ export function toHandlers( } return ret } + +export function checkDynamicEvent( + eventName: string, + modifierPostfix: string, +): string { + if (eventName != null && eventName !== '') return eventName + modifierPostfix + return '' +} diff --git a/packages/runtime-core/src/index.ts b/packages/runtime-core/src/index.ts index 9910f8210..eabf3eb6e 100644 --- a/packages/runtime-core/src/index.ts +++ b/packages/runtime-core/src/index.ts @@ -358,7 +358,7 @@ export { withScopeId, } from './componentRenderContext' export { renderList } from './helpers/renderList' -export { toHandlers } from './helpers/toHandlers' +export { toHandlers, checkDynamicEvent } from './helpers/toHandlers' export { renderSlot } from './helpers/renderSlot' export { createSlots } from './helpers/createSlots' export { withMemo, isMemoSame } from './helpers/withMemo' From ee324fbc45480444bac097be565414d1d52dd689 Mon Sep 17 00:00:00 2001 From: linzhe141 <1572213544@qq.com> Date: Tue, 18 Mar 2025 11:50:33 +0800 Subject: [PATCH 2/4] chore: update test --- .../transforms/__snapshots__/vOn.spec.ts.snap | 13 +++++++++++++ .../compiler-dom/__tests__/transforms/vOn.spec.ts | 7 +++++++ 2 files changed, 20 insertions(+) create mode 100644 packages/compiler-dom/__tests__/transforms/__snapshots__/vOn.spec.ts.snap diff --git a/packages/compiler-dom/__tests__/transforms/__snapshots__/vOn.spec.ts.snap b/packages/compiler-dom/__tests__/transforms/__snapshots__/vOn.spec.ts.snap new file mode 100644 index 000000000..d49d731bf --- /dev/null +++ b/packages/compiler-dom/__tests__/transforms/__snapshots__/vOn.spec.ts.snap @@ -0,0 +1,13 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`compiler-dom: transform v-on > should wrap both for dynamic key event w/ once modifiers 1`] = ` +"const _Vue = Vue + +return function render(_ctx, _cache) { + with (_ctx) { + const { toHandlerKey: _toHandlerKey, checkDynamicEvent: _checkDynamicEvent, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue + + return (_openBlock(), _createElementBlock("div", { [_checkDynamicEvent(_toHandlerKey(e),"Once")]: test }, null, 16 /* FULL_PROPS */)) + } +}" +`; diff --git a/packages/compiler-dom/__tests__/transforms/vOn.spec.ts b/packages/compiler-dom/__tests__/transforms/vOn.spec.ts index ee9ea93c3..896d3dfed 100644 --- a/packages/compiler-dom/__tests__/transforms/vOn.spec.ts +++ b/packages/compiler-dom/__tests__/transforms/vOn.spec.ts @@ -6,6 +6,7 @@ import { type ObjectExpression, TO_HANDLER_KEY, type VNodeCall, + generate, helperNameMap, baseParse as parse, transform, @@ -168,6 +169,12 @@ describe('compiler-dom: transform v-on', () => { }) }) + it('should wrap both for dynamic key event w/ once modifiers', () => { + const { root: ast } = parseWithVOn(`
`) + + expect(generate(ast).code).toMatchSnapshot() + }) + it('should not wrap normal guard if there is only keys guard', () => { const { props: [prop], From 60a554cd86c0058883a14052114d74efbcbb65cc Mon Sep 17 00:00:00 2001 From: linzhe141 <1572213544@qq.com> Date: Tue, 18 Mar 2025 13:24:23 +0800 Subject: [PATCH 3/4] chore: update --- .../transforms/__snapshots__/vOn.spec.ts.snap | 10 +++++++--- packages/compiler-dom/__tests__/transforms/vOn.spec.ts | 6 ++++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/packages/compiler-dom/__tests__/transforms/__snapshots__/vOn.spec.ts.snap b/packages/compiler-dom/__tests__/transforms/__snapshots__/vOn.spec.ts.snap index d49d731bf..7042b748d 100644 --- a/packages/compiler-dom/__tests__/transforms/__snapshots__/vOn.spec.ts.snap +++ b/packages/compiler-dom/__tests__/transforms/__snapshots__/vOn.spec.ts.snap @@ -1,13 +1,17 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`compiler-dom: transform v-on > should wrap both for dynamic key event w/ once modifiers 1`] = ` +exports[`compiler-dom: transform v-on > should wrap both for dynamic key event w/ event modifiers 1`] = ` "const _Vue = Vue return function render(_ctx, _cache) { with (_ctx) { - const { toHandlerKey: _toHandlerKey, checkDynamicEvent: _checkDynamicEvent, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue + const { toHandlerKey: _toHandlerKey, checkDynamicEvent: _checkDynamicEvent, createElementVNode: _createElementVNode, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue - return (_openBlock(), _createElementBlock("div", { [_checkDynamicEvent(_toHandlerKey(e),"Once")]: test }, null, 16 /* FULL_PROPS */)) + return (_openBlock(), _createElementBlock(_Fragment, null, [ + _createElementVNode("div", { [_checkDynamicEvent(_toHandlerKey(e),"Once")]: test }, null, 16 /* FULL_PROPS */), + _createElementVNode("div", { [_checkDynamicEvent(_toHandlerKey(e),"Passive")]: test }, null, 16 /* FULL_PROPS */), + _createElementVNode("div", { [_checkDynamicEvent(_toHandlerKey(e),"Capture")]: test }, null, 16 /* FULL_PROPS */) + ], 64 /* STABLE_FRAGMENT */)) } }" `; diff --git a/packages/compiler-dom/__tests__/transforms/vOn.spec.ts b/packages/compiler-dom/__tests__/transforms/vOn.spec.ts index 896d3dfed..497716ee6 100644 --- a/packages/compiler-dom/__tests__/transforms/vOn.spec.ts +++ b/packages/compiler-dom/__tests__/transforms/vOn.spec.ts @@ -169,8 +169,10 @@ describe('compiler-dom: transform v-on', () => { }) }) - it('should wrap both for dynamic key event w/ once modifiers', () => { - const { root: ast } = parseWithVOn(`
`) + it('should wrap both for dynamic key event w/ event modifiers', () => { + const { root: ast } = parseWithVOn( + `
`, + ) expect(generate(ast).code).toMatchSnapshot() }) From d2d2e3d08df9cb41b77905daeb0730ef2881460b Mon Sep 17 00:00:00 2001 From: linzhe141 <1572213544@qq.com> Date: Tue, 18 Mar 2025 14:12:57 +0800 Subject: [PATCH 4/4] chore: update --- packages/compiler-core/src/runtimeHelpers.ts | 4 ---- .../transforms/__snapshots__/vOn.spec.ts.snap | 8 ++++---- packages/compiler-dom/src/runtimeHelpers.ts | 4 ++++ packages/compiler-dom/src/transforms/vOn.ts | 11 +++++++---- packages/runtime-core/src/helpers/toHandlers.ts | 8 -------- packages/runtime-core/src/index.ts | 2 +- packages/runtime-dom/src/directives/vOn.ts | 11 +++++++++++ packages/runtime-dom/src/index.ts | 6 +++++- 8 files changed, 32 insertions(+), 22 deletions(-) diff --git a/packages/compiler-core/src/runtimeHelpers.ts b/packages/compiler-core/src/runtimeHelpers.ts index 05684f7ef..7cf3757b2 100644 --- a/packages/compiler-core/src/runtimeHelpers.ts +++ b/packages/compiler-core/src/runtimeHelpers.ts @@ -63,9 +63,6 @@ export const CAPITALIZE: unique symbol = Symbol(__DEV__ ? `capitalize` : ``) export const TO_HANDLER_KEY: unique symbol = Symbol( __DEV__ ? `toHandlerKey` : ``, ) -export const CHECK_DYNAMIC_EVENT: unique symbol = Symbol( - __DEV__ ? `checkDynamicEvent` : ``, -) export const SET_BLOCK_TRACKING: unique symbol = Symbol( __DEV__ ? `setBlockTracking` : ``, ) @@ -118,7 +115,6 @@ export const helperNameMap: Record = { [CAMELIZE]: `camelize`, [CAPITALIZE]: `capitalize`, [TO_HANDLER_KEY]: `toHandlerKey`, - [CHECK_DYNAMIC_EVENT]: `checkDynamicEvent`, [SET_BLOCK_TRACKING]: `setBlockTracking`, [PUSH_SCOPE_ID]: `pushScopeId`, [POP_SCOPE_ID]: `popScopeId`, diff --git a/packages/compiler-dom/__tests__/transforms/__snapshots__/vOn.spec.ts.snap b/packages/compiler-dom/__tests__/transforms/__snapshots__/vOn.spec.ts.snap index 7042b748d..6f4e33635 100644 --- a/packages/compiler-dom/__tests__/transforms/__snapshots__/vOn.spec.ts.snap +++ b/packages/compiler-dom/__tests__/transforms/__snapshots__/vOn.spec.ts.snap @@ -5,12 +5,12 @@ exports[`compiler-dom: transform v-on > should wrap both for dynamic key event w return function render(_ctx, _cache) { with (_ctx) { - const { toHandlerKey: _toHandlerKey, checkDynamicEvent: _checkDynamicEvent, createElementVNode: _createElementVNode, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue + const { toHandlerKey: _toHandlerKey, withDynamicEventModifiers: _withDynamicEventModifiers, createElementVNode: _createElementVNode, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock } = _Vue return (_openBlock(), _createElementBlock(_Fragment, null, [ - _createElementVNode("div", { [_checkDynamicEvent(_toHandlerKey(e),"Once")]: test }, null, 16 /* FULL_PROPS */), - _createElementVNode("div", { [_checkDynamicEvent(_toHandlerKey(e),"Passive")]: test }, null, 16 /* FULL_PROPS */), - _createElementVNode("div", { [_checkDynamicEvent(_toHandlerKey(e),"Capture")]: test }, null, 16 /* FULL_PROPS */) + _createElementVNode("div", { [_withDynamicEventModifiers(_toHandlerKey(e), "Once")]: test }, null, 16 /* FULL_PROPS */), + _createElementVNode("div", { [_withDynamicEventModifiers(_toHandlerKey(e), "Passive")]: test }, null, 16 /* FULL_PROPS */), + _createElementVNode("div", { [_withDynamicEventModifiers(_toHandlerKey(e), "Capture")]: test }, null, 16 /* FULL_PROPS */) ], 64 /* STABLE_FRAGMENT */)) } }" diff --git a/packages/compiler-dom/src/runtimeHelpers.ts b/packages/compiler-dom/src/runtimeHelpers.ts index c5349ad79..1723ca111 100644 --- a/packages/compiler-dom/src/runtimeHelpers.ts +++ b/packages/compiler-dom/src/runtimeHelpers.ts @@ -18,6 +18,9 @@ export const V_ON_WITH_MODIFIERS: unique symbol = Symbol( export const V_ON_WITH_KEYS: unique symbol = Symbol( __DEV__ ? `vOnKeysGuard` : ``, ) +export const V_ON_WITH_DYNAMIC_EVENT_MODIFIERS: unique symbol = Symbol( + __DEV__ ? `vOnDynamicEventModifiers` : ``, +) export const V_SHOW: unique symbol = Symbol(__DEV__ ? `vShow` : ``) @@ -34,6 +37,7 @@ registerRuntimeHelpers({ [V_MODEL_DYNAMIC]: `vModelDynamic`, [V_ON_WITH_MODIFIERS]: `withModifiers`, [V_ON_WITH_KEYS]: `withKeys`, + [V_ON_WITH_DYNAMIC_EVENT_MODIFIERS]: `withDynamicEventModifiers`, [V_SHOW]: `vShow`, [TRANSITION]: `Transition`, [TRANSITION_GROUP]: `TransitionGroup`, diff --git a/packages/compiler-dom/src/transforms/vOn.ts b/packages/compiler-dom/src/transforms/vOn.ts index d4fac6830..6eefff935 100644 --- a/packages/compiler-dom/src/transforms/vOn.ts +++ b/packages/compiler-dom/src/transforms/vOn.ts @@ -1,5 +1,4 @@ import { - CHECK_DYNAMIC_EVENT, CompilerDeprecationTypes, type DirectiveTransform, type ExpressionNode, @@ -15,7 +14,11 @@ import { createSimpleExpression, isStaticExp, } from '@vue/compiler-core' -import { V_ON_WITH_KEYS, V_ON_WITH_MODIFIERS } from '../runtimeHelpers' +import { + V_ON_WITH_DYNAMIC_EVENT_MODIFIERS, + V_ON_WITH_KEYS, + V_ON_WITH_MODIFIERS, +} from '../runtimeHelpers' import { capitalize, makeMap } from '@vue/shared' const isEventOptionModifier = /*@__PURE__*/ makeMap(`passive,once,capture`) @@ -146,9 +149,9 @@ export const transformOn: DirectiveTransform = (dir, node, context) => { key = isStaticExp(key) ? createSimpleExpression(`${key.content}${modifierPostfix}`, true) : createCompoundExpression([ - `${context.helperString(CHECK_DYNAMIC_EVENT)}(`, + `${context.helperString(V_ON_WITH_DYNAMIC_EVENT_MODIFIERS)}(`, key, - `,"${modifierPostfix}")`, + `, "${modifierPostfix}")`, ]) } diff --git a/packages/runtime-core/src/helpers/toHandlers.ts b/packages/runtime-core/src/helpers/toHandlers.ts index 6d2339d6a..3e7dcb327 100644 --- a/packages/runtime-core/src/helpers/toHandlers.ts +++ b/packages/runtime-core/src/helpers/toHandlers.ts @@ -23,11 +23,3 @@ export function toHandlers( } return ret } - -export function checkDynamicEvent( - eventName: string, - modifierPostfix: string, -): string { - if (eventName != null && eventName !== '') return eventName + modifierPostfix - return '' -} diff --git a/packages/runtime-core/src/index.ts b/packages/runtime-core/src/index.ts index eabf3eb6e..9910f8210 100644 --- a/packages/runtime-core/src/index.ts +++ b/packages/runtime-core/src/index.ts @@ -358,7 +358,7 @@ export { withScopeId, } from './componentRenderContext' export { renderList } from './helpers/renderList' -export { toHandlers, checkDynamicEvent } from './helpers/toHandlers' +export { toHandlers } from './helpers/toHandlers' export { renderSlot } from './helpers/renderSlot' export { createSlots } from './helpers/createSlots' export { withMemo, isMemoSame } from './helpers/withMemo' diff --git a/packages/runtime-dom/src/directives/vOn.ts b/packages/runtime-dom/src/directives/vOn.ts index c1a2e182f..11e25a9a5 100644 --- a/packages/runtime-dom/src/directives/vOn.ts +++ b/packages/runtime-dom/src/directives/vOn.ts @@ -160,4 +160,15 @@ export const withKeys = any>( ) } +/** + * @private + */ +export function withDynamicEventModifiers( + eventName: string, + modifierPostfix: string, +): string { + if (eventName != null && eventName !== '') return eventName + modifierPostfix + return '' +} + export type VOnDirective = Directive diff --git a/packages/runtime-dom/src/index.ts b/packages/runtime-dom/src/index.ts index ca9a307dd..9da9c3628 100644 --- a/packages/runtime-dom/src/index.ts +++ b/packages/runtime-dom/src/index.ts @@ -280,7 +280,11 @@ export { vModelSelect, vModelDynamic, } from './directives/vModel' -export { withModifiers, withKeys } from './directives/vOn' +export { + withModifiers, + withKeys, + withDynamicEventModifiers, +} from './directives/vOn' export { vShow } from './directives/vShow' import { initVModelForSSR } from './directives/vModel'