From 4d94ebfe75174b340d2b794e699cad1add3600a9 Mon Sep 17 00:00:00 2001 From: Evan You Date: Thu, 30 Nov 2023 19:26:36 +0800 Subject: [PATCH] perf(v-on): constant handlers with modifiers should not be treated as dynamic --- .../transforms/transformElement.spec.ts | 14 +++++++++++ .../src/transforms/transformElement.ts | 9 ++++++- .../__tests__/transforms/vOn.spec.ts | 24 +++++++++++++++---- 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/packages/compiler-core/__tests__/transforms/transformElement.spec.ts b/packages/compiler-core/__tests__/transforms/transformElement.spec.ts index c83bdeebef2..678d01cbc7d 100644 --- a/packages/compiler-core/__tests__/transforms/transformElement.spec.ts +++ b/packages/compiler-core/__tests__/transforms/transformElement.spec.ts @@ -1160,6 +1160,20 @@ describe('compiler: element transform', () => { genFlagText([PatchFlags.PROPS, PatchFlags.NEED_HYDRATION]) ) }) + + test('should not have PROPS patchflag for constant v-on handlers', () => { + const { node } = parseWithElementTransform(`
`, { + prefixIdentifiers: true, + bindingMetadata: { + foo: BindingTypes.SETUP_CONST + }, + directiveTransforms: { + on: transformOn + } + }) + // should only have hydration flag + expect(node.patchFlag).toBe(genFlagText(PatchFlags.NEED_HYDRATION)) + }) }) describe('dynamic component', () => { diff --git a/packages/compiler-core/src/transforms/transformElement.ts b/packages/compiler-core/src/transforms/transformElement.ts index 2b5f23a6177..ccede37777d 100644 --- a/packages/compiler-core/src/transforms/transformElement.ts +++ b/packages/compiler-core/src/transforms/transformElement.ts @@ -19,7 +19,8 @@ import { TemplateTextChildNode, DirectiveArguments, createVNodeCall, - ConstantTypes + ConstantTypes, + JSChildNode } from '../ast' import { PatchFlags, @@ -459,6 +460,12 @@ export function buildProps( hasVnodeHook = true } + if (isEventHandler && value.type === NodeTypes.JS_CALL_EXPRESSION) { + // handler wrapped with internal helper e.g. withModifiers(fn) + // extract the actual expression + value = value.arguments[0] as JSChildNode + } + if ( value.type === NodeTypes.JS_CACHE_EXPRESSION || ((value.type === NodeTypes.SIMPLE_EXPRESSION || diff --git a/packages/compiler-dom/__tests__/transforms/vOn.spec.ts b/packages/compiler-dom/__tests__/transforms/vOn.spec.ts index 79ffcdef03c..42b4cd79888 100644 --- a/packages/compiler-dom/__tests__/transforms/vOn.spec.ts +++ b/packages/compiler-dom/__tests__/transforms/vOn.spec.ts @@ -7,7 +7,8 @@ import { NodeTypes, ObjectExpression, transform, - VNodeCall + VNodeCall, + BindingTypes } from '@vue/compiler-core' import { transformOn } from '../../src/transforms/vOn' import { V_ON_WITH_KEYS, V_ON_WITH_MODIFIERS } from '../../src/runtimeHelpers' @@ -25,12 +26,11 @@ function parseWithVOn(template: string, options: CompilerOptions = {}) { }, ...options }) + const node = (ast.children[0] as ElementNode).codegenNode as VNodeCall return { root: ast, - props: ( - ((ast.children[0] as ElementNode).codegenNode as VNodeCall) - .props as ObjectExpression - ).properties + node, + props: (node.props as ObjectExpression).properties } } @@ -288,4 +288,18 @@ describe('compiler-dom: transform v-on', () => { } }) }) + + test('should not have PROPS patchFlag for constant v-on handlers with modifiers', () => { + const { node } = parseWithVOn(`
`, { + prefixIdentifiers: true, + bindingMetadata: { + foo: BindingTypes.SETUP_CONST + }, + directiveTransforms: { + on: transformOn + } + }) + // should only have hydration flag + expect(node.patchFlag).toBe(genFlagText(PatchFlags.NEED_HYDRATION)) + }) })