From: 三咲智子 Kevin Deng Date: Sat, 9 Dec 2023 16:06:20 +0000 (+0800) Subject: refactor(compiler-vapor): v-on X-Git-Tag: v3.6.0-alpha.1~16^2~723 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=da8e196ca5ccc52d8908a10ad093c2804118def7;p=thirdparty%2Fvuejs%2Fcore.git refactor(compiler-vapor): v-on --- diff --git a/packages/compiler-core/src/utils.ts b/packages/compiler-core/src/utils.ts index a1e084eb97..93b990dbbc 100644 --- a/packages/compiler-core/src/utils.ts +++ b/packages/compiler-core/src/utils.ts @@ -152,11 +152,17 @@ export const isMemberExpressionBrowser = (path: string): boolean => { } export const isMemberExpressionNode = __BROWSER__ - ? (NOOP as any as (path: string, context: TransformContext) => boolean) - : (path: string, context: TransformContext): boolean => { + ? (NOOP as any as ( + path: string, + options: Pick + ) => boolean) + : ( + path: string, + options: Pick + ): boolean => { try { let ret: Expression = parseExpression(path, { - plugins: context.expressionPlugins + plugins: options.expressionPlugins }) if (ret.type === 'TSAsExpression' || ret.type === 'TSTypeAssertion') { ret = ret.expression diff --git a/packages/compiler-vapor/src/generate.ts b/packages/compiler-vapor/src/generate.ts index 0a71f074db..e9427f4740 100644 --- a/packages/compiler-vapor/src/generate.ts +++ b/packages/compiler-vapor/src/generate.ts @@ -438,31 +438,48 @@ function genSetEvent(oper: SetEventIRNode, context: CodegenContext) { const { vaporHelper, push, pushWithNewline } = context pushWithNewline(`${vaporHelper('on')}(n${oper.element}, `) - // second arg: event name - genExpression(oper.key, context) - push(', ') - const { keys, nonKeys, options } = oper.modifiers - if (keys.length) { - push(`${vaporHelper('withKeys')}(`) - } - if (nonKeys.length) { - push(`${vaporHelper('withModifiers')}(`) + // 2nd arg: event name + if (oper.keyOverride) { + const find = JSON.stringify(oper.keyOverride[0]) + const replacement = JSON.stringify(oper.keyOverride[1]) + push('(') + genExpression(oper.key, context) + push(`) === ${find} ? ${replacement} : (`) + genExpression(oper.key, context) + push(')') + } else { + genExpression(oper.key, context) } + push(', ') - // gen event handler - push('(...args) => (') - genExpression(oper.value, context) - push(' && ') - genExpression(oper.value, context) - push('(...args))') + const { keys, nonKeys, options } = oper.modifiers - if (nonKeys.length) { - push(`, ${genArrayExpression(nonKeys)})`) - } - if (keys.length) { - push(`, ${genArrayExpression(keys)})`) + // 3rd arg: event handler + if (oper.value && oper.value.content.trim()) { + if (keys.length) { + push(`${vaporHelper('withKeys')}(`) + } + if (nonKeys.length) { + push(`${vaporHelper('withModifiers')}(`) + } + push('(...args) => (') + genExpression(oper.value, context) + push(' && ') + genExpression(oper.value, context) + push('(...args))') + + if (nonKeys.length) { + push(`, ${genArrayExpression(nonKeys)})`) + } + if (keys.length) { + push(`, ${genArrayExpression(keys)})`) + } + } else { + push('() => {}') } + + // 4th arg, gen options if (options.length) { push(`, { ${options.map((v) => `${v}: true`).join(', ')} }`) } diff --git a/packages/compiler-vapor/src/ir.ts b/packages/compiler-vapor/src/ir.ts index 979536af80..2af5455d62 100644 --- a/packages/compiler-vapor/src/ir.ts +++ b/packages/compiler-vapor/src/ir.ts @@ -69,11 +69,12 @@ export interface SetTextIRNode extends BaseIRNode { value: IRExpression } +export type KeyOverride = [find: string, replacement: string] export interface SetEventIRNode extends BaseIRNode { type: IRNodeTypes.SET_EVENT element: number key: IRExpression - value: IRExpression + value?: SimpleExpressionNode modifiers: { // modifiers for addEventListener() options, e.g. .passive & .capture options: string[] @@ -82,6 +83,7 @@ export interface SetEventIRNode extends BaseIRNode { // modifiers that needs runtime guards, withModifiers nonKeys: string[] } + keyOverride?: KeyOverride } export interface SetHtmlIRNode extends BaseIRNode { diff --git a/packages/compiler-vapor/src/transforms/vOn.ts b/packages/compiler-vapor/src/transforms/vOn.ts index f1764ffb0f..de5fc38a93 100644 --- a/packages/compiler-vapor/src/transforms/vOn.ts +++ b/packages/compiler-vapor/src/transforms/vOn.ts @@ -1,70 +1,64 @@ -import { - createCompilerError, - createSimpleExpression, - ErrorCodes, - ExpressionNode, - isStaticExp, - NodeTypes, -} from '@vue/compiler-core' +import { createCompilerError, ErrorCodes } from '@vue/compiler-core' import type { DirectiveTransform } from '../transform' -import { IRNodeTypes } from '../ir' +import { IRNodeTypes, KeyOverride } from '../ir' import { resolveModifiers } from '@vue/compiler-dom' export const transformVOn: DirectiveTransform = (dir, node, context) => { - const { arg, exp, loc, modifiers } = dir + let { arg, exp, loc, modifiers } = dir if (!exp && !modifiers.length) { context.options.onError( createCompilerError(ErrorCodes.X_V_ON_NO_EXPRESSION, loc), ) - return } if (!arg) { // TODO support v-on="{}" return - } else if (exp === undefined) { - // TODO X_V_ON_NO_EXPRESSION error - return } - const handlerKey = `on${arg.content}` const { keyModifiers, nonKeyModifiers, eventOptionModifiers } = - resolveModifiers(handlerKey, modifiers, null, loc) + resolveModifiers( + arg.isStatic ? `on${arg.content}` : arg, + modifiers, + null, + loc, + ) + + let keyOverride: KeyOverride | undefined // normalize click.right and click.middle since they don't actually fire - let name = arg.content + + const isStaticClick = arg.isStatic && arg.content.toLowerCase() === 'click' + if (nonKeyModifiers.includes('right')) { - name = transformClick(arg, 'contextmenu') + if (isStaticClick) { + arg = { ...arg, content: 'contextmenu' } + } else if (!arg.isStatic) { + keyOverride = ['click', 'contextmenu'] + } } if (nonKeyModifiers.includes('middle')) { - name = transformClick(arg, 'mouseup') + if (keyOverride) { + // TODO error here + } + if (isStaticClick) { + arg = { ...arg, content: 'mouseup' } + } else if (!arg.isStatic) { + keyOverride = ['click', 'mouseup'] + } } - // TODO reactive context.registerOperation({ type: IRNodeTypes.SET_EVENT, loc, element: context.reference(), - key: createSimpleExpression(name, true, arg.loc), + key: arg, value: exp, modifiers: { keys: keyModifiers, nonKeys: nonKeyModifiers, options: eventOptionModifiers, }, + keyOverride, }) } - -function transformClick(key: ExpressionNode, event: string) { - const isStaticClick = - isStaticExp(key) && key.content.toLowerCase() === 'click' - - if (isStaticClick) { - return event - } else if (key.type !== NodeTypes.SIMPLE_EXPRESSION) { - // TODO: handle CompoundExpression - return 'TODO' - } else { - return key.content.toLowerCase() - } -}