]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
refactor(compiler-vapor): v-on
author三咲智子 Kevin Deng <sxzz@sxzz.moe>
Sat, 9 Dec 2023 16:06:20 +0000 (00:06 +0800)
committer三咲智子 Kevin Deng <sxzz@sxzz.moe>
Sat, 9 Dec 2023 16:06:20 +0000 (00:06 +0800)
packages/compiler-core/src/utils.ts
packages/compiler-vapor/src/generate.ts
packages/compiler-vapor/src/ir.ts
packages/compiler-vapor/src/transforms/vOn.ts

index a1e084eb974405e63d3b7e9b3ba0ed719f9a8b1c..93b990dbbce63c4b35044ff4c4d6f9c43c510722 100644 (file)
@@ -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<TransformContext, 'expressionPlugins'>
+    ) => boolean)
+  : (
+      path: string,
+      options: Pick<TransformContext, 'expressionPlugins'>
+    ): boolean => {
       try {
         let ret: Expression = parseExpression(path, {
-          plugins: context.expressionPlugins
+          plugins: options.expressionPlugins
         })
         if (ret.type === 'TSAsExpression' || ret.type === 'TSTypeAssertion') {
           ret = ret.expression
index 0a71f074db7c7319e219c28a9c3b8ed9a1cb7783..e9427f47409a0bb56988171512b3fa698c4f273b 100644 (file)
@@ -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(', ')} }`)
   }
index 979536af80d3e1575ad5928ebddbf104ade3502d..2af5455d628eec80cc19dbf25f325a7cff3a767c 100644 (file)
@@ -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 {
index f1764ffb0fdc03ad4e67a0cb853baec23d1f7647..de5fc38a93912e9b275e093d2ddf88801eeb9342 100644 (file)
@@ -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()
-  }
-}