|
@@ -4,18 +4,23 @@ import {
|
|
|
createSimpleExpression,
|
|
createSimpleExpression,
|
|
|
ExpressionNode,
|
|
ExpressionNode,
|
|
|
NodeTypes,
|
|
NodeTypes,
|
|
|
- createCompoundExpression
|
|
|
|
|
|
|
+ createCompoundExpression,
|
|
|
|
|
+ SimpleExpressionNode
|
|
|
} from '../ast'
|
|
} from '../ast'
|
|
|
import { capitalize } from '@vue/shared'
|
|
import { capitalize } from '@vue/shared'
|
|
|
import { createCompilerError, ErrorCodes } from '../errors'
|
|
import { createCompilerError, ErrorCodes } from '../errors'
|
|
|
|
|
+import { processExpression } from './transformExpression'
|
|
|
|
|
+
|
|
|
|
|
+const fnExpRE = /^([\w$_]+|\([^)]*?\))\s*=>|^function(?:\s+[\w$]+)?\s*\(/
|
|
|
|
|
+const simplePathRE = /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['[^']*?']|\["[^"]*?"]|\[\d+]|\[[A-Za-z_$][\w$]*])*$/
|
|
|
|
|
|
|
|
// v-on without arg is handled directly in ./element.ts due to it affecting
|
|
// v-on without arg is handled directly in ./element.ts due to it affecting
|
|
|
// codegen for the entire props object. This transform here is only for v-on
|
|
// codegen for the entire props object. This transform here is only for v-on
|
|
|
// *with* args.
|
|
// *with* args.
|
|
|
export const transformOn: DirectiveTransform = (dir, context) => {
|
|
export const transformOn: DirectiveTransform = (dir, context) => {
|
|
|
- const { exp, loc, modifiers } = dir
|
|
|
|
|
|
|
+ const { loc, modifiers } = dir
|
|
|
const arg = dir.arg!
|
|
const arg = dir.arg!
|
|
|
- if (!exp && !modifiers.length) {
|
|
|
|
|
|
|
+ if (!dir.exp && !modifiers.length) {
|
|
|
context.onError(createCompilerError(ErrorCodes.X_V_ON_NO_EXPRESSION, loc))
|
|
context.onError(createCompilerError(ErrorCodes.X_V_ON_NO_EXPRESSION, loc))
|
|
|
}
|
|
}
|
|
|
let eventName: ExpressionNode
|
|
let eventName: ExpressionNode
|
|
@@ -37,10 +42,36 @@ export const transformOn: DirectiveTransform = (dir, context) => {
|
|
|
}
|
|
}
|
|
|
// TODO .once modifier handling since it is platform agnostic
|
|
// TODO .once modifier handling since it is platform agnostic
|
|
|
// other modifiers are handled in compiler-dom
|
|
// other modifiers are handled in compiler-dom
|
|
|
|
|
+
|
|
|
|
|
+ // handler processing
|
|
|
|
|
+ if (dir.exp) {
|
|
|
|
|
+ // exp is guarunteed to be a simple expression here because v-on w/ arg is
|
|
|
|
|
+ // skipped by transformExpression as a special case.
|
|
|
|
|
+ let exp: ExpressionNode = dir.exp as SimpleExpressionNode
|
|
|
|
|
+ const isInlineStatement = !(
|
|
|
|
|
+ simplePathRE.test(exp.content) || fnExpRE.test(exp.content)
|
|
|
|
|
+ )
|
|
|
|
|
+ // process the expression since it's been skipped
|
|
|
|
|
+ if (!__BROWSER__ && context.prefixIdentifiers) {
|
|
|
|
|
+ context.addIdentifiers(`$event`)
|
|
|
|
|
+ exp = processExpression(exp, context)
|
|
|
|
|
+ context.removeIdentifiers(`$event`)
|
|
|
|
|
+ }
|
|
|
|
|
+ if (isInlineStatement) {
|
|
|
|
|
+ // wrap inline statement in a function expression
|
|
|
|
|
+ exp = createCompoundExpression([
|
|
|
|
|
+ `$event => (`,
|
|
|
|
|
+ ...(exp.type === NodeTypes.SIMPLE_EXPRESSION ? [exp] : exp.children),
|
|
|
|
|
+ `)`
|
|
|
|
|
+ ])
|
|
|
|
|
+ }
|
|
|
|
|
+ dir.exp = exp
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
return {
|
|
return {
|
|
|
props: createObjectProperty(
|
|
props: createObjectProperty(
|
|
|
eventName,
|
|
eventName,
|
|
|
- exp || createSimpleExpression(`() => {}`, false, loc)
|
|
|
|
|
|
|
+ dir.exp || createSimpleExpression(`() => {}`, false, loc)
|
|
|
),
|
|
),
|
|
|
needRuntime: false
|
|
needRuntime: false
|
|
|
}
|
|
}
|