diff --git a/packages/compiler-core/__tests__/parse.spec.ts b/packages/compiler-core/__tests__/parse.spec.ts index 22fb209cfb9..37e81e64924 100644 --- a/packages/compiler-core/__tests__/parse.spec.ts +++ b/packages/compiler-core/__tests__/parse.spec.ts @@ -1358,7 +1358,27 @@ describe('compiler: parse', () => { name: 'on', rawName: 'v-on.enter', arg: undefined, - modifiers: ['enter'], + modifiers: [ + { + constType: 3, + content: 'enter', + isStatic: true, + loc: { + end: { + column: 16, + line: 1, + offset: 15, + }, + source: 'enter', + start: { + column: 11, + line: 1, + offset: 10, + }, + }, + type: 4, + }, + ], exp: undefined, loc: { start: { offset: 5, line: 1, column: 6 }, @@ -1377,7 +1397,46 @@ describe('compiler: parse', () => { name: 'on', rawName: 'v-on.enter.exact', arg: undefined, - modifiers: ['enter', 'exact'], + modifiers: [ + { + constType: 3, + content: 'enter', + isStatic: true, + loc: { + end: { + column: 16, + line: 1, + offset: 15, + }, + source: 'enter', + start: { + column: 11, + line: 1, + offset: 10, + }, + }, + type: 4, + }, + { + constType: 3, + content: 'exact', + isStatic: true, + loc: { + end: { + column: 22, + line: 1, + offset: 21, + }, + source: 'exact', + start: { + column: 17, + line: 1, + offset: 16, + }, + }, + type: 4, + }, + ], exp: undefined, loc: { start: { offset: 5, line: 1, column: 6 }, @@ -1406,7 +1465,46 @@ describe('compiler: parse', () => { source: 'click', }, }, - modifiers: ['enter', 'exact'], + modifiers: [ + { + constType: 3, + content: 'enter', + isStatic: true, + loc: { + end: { + column: 22, + line: 1, + offset: 21, + }, + source: 'enter', + start: { + column: 17, + line: 1, + offset: 16, + }, + }, + type: 4, + }, + { + constType: 3, + content: 'exact', + isStatic: true, + loc: { + end: { + column: 28, + line: 1, + offset: 27, + }, + source: 'exact', + start: { + column: 23, + line: 1, + offset: 22, + }, + }, + type: 4, + }, + ], exp: undefined, loc: { start: { offset: 5, line: 1, column: 6 }, @@ -1435,7 +1533,27 @@ describe('compiler: parse', () => { source: '[a.b]', }, }, - modifiers: ['camel'], + modifiers: [ + { + constType: 3, + content: 'camel', + isStatic: true, + loc: { + end: { + column: 22, + line: 1, + offset: 21, + }, + source: 'camel', + start: { + column: 17, + line: 1, + offset: 16, + }, + }, + type: 4, + }, + ], exp: undefined, loc: { start: { offset: 5, line: 1, column: 6 }, @@ -1530,7 +1648,27 @@ describe('compiler: parse', () => { source: 'a', }, }, - modifiers: ['prop'], + modifiers: [ + { + constType: 0, + content: 'prop', + isStatic: false, + loc: { + end: { + column: 1, + line: 1, + offset: 0, + }, + source: '', + start: { + column: 1, + line: 1, + offset: 0, + }, + }, + type: 4, + }, + ], exp: { type: NodeTypes.SIMPLE_EXPRESSION, content: 'b', @@ -1569,7 +1707,27 @@ describe('compiler: parse', () => { source: 'a', }, }, - modifiers: ['sync'], + modifiers: [ + { + constType: 3, + content: 'sync', + isStatic: true, + loc: { + end: { + column: 13, + line: 1, + offset: 12, + }, + source: 'sync', + start: { + column: 9, + line: 1, + offset: 8, + }, + }, + type: 4, + }, + ], exp: { type: NodeTypes.SIMPLE_EXPRESSION, content: 'b', @@ -1649,7 +1807,27 @@ describe('compiler: parse', () => { source: 'a', }, }, - modifiers: ['enter'], + modifiers: [ + { + constType: 3, + content: 'enter', + isStatic: true, + loc: { + end: { + column: 14, + line: 1, + offset: 13, + }, + source: 'enter', + start: { + column: 9, + line: 1, + offset: 8, + }, + }, + type: 4, + }, + ], exp: { type: NodeTypes.SIMPLE_EXPRESSION, content: 'b', diff --git a/packages/compiler-core/src/ast.ts b/packages/compiler-core/src/ast.ts index 8116f532b79..cfd5fee2569 100644 --- a/packages/compiler-core/src/ast.ts +++ b/packages/compiler-core/src/ast.ts @@ -203,7 +203,7 @@ export interface DirectiveNode extends Node { rawName?: string exp: ExpressionNode | undefined arg: ExpressionNode | undefined - modifiers: string[] + modifiers: SimpleExpressionNode[] /** * optional property to cache the expression parse result for v-for */ diff --git a/packages/compiler-core/src/parser.ts b/packages/compiler-core/src/parser.ts index cac943dd63d..304807d076a 100644 --- a/packages/compiler-core/src/parser.ts +++ b/packages/compiler-core/src/parser.ts @@ -225,7 +225,7 @@ const tokenizer = new Tokenizer(stack, { rawName: raw, exp: undefined, arg: undefined, - modifiers: raw === '.' ? ['prop'] : [], + modifiers: raw === '.' ? [createSimpleExpression('prop')] : [], loc: getLoc(start), } if (name === 'pre') { @@ -273,7 +273,8 @@ const tokenizer = new Tokenizer(stack, { setLocEnd(arg.loc, end) } } else { - ;(currentProp as DirectiveNode).modifiers.push(mod) + const exp = createSimpleExpression(mod, true, getLoc(start, end)) + ;(currentProp as DirectiveNode).modifiers.push(exp) } }, @@ -379,7 +380,9 @@ const tokenizer = new Tokenizer(stack, { if ( __COMPAT__ && currentProp.name === 'bind' && - (syncIndex = currentProp.modifiers.indexOf('sync')) > -1 && + (syncIndex = currentProp.modifiers.findIndex( + mod => mod.content === 'sync', + )) > -1 && checkCompatEnabled( CompilerDeprecationTypes.COMPILER_V_BIND_SYNC, currentOptions, diff --git a/packages/compiler-core/src/transforms/transformElement.ts b/packages/compiler-core/src/transforms/transformElement.ts index c917436ea91..76ca1d44353 100644 --- a/packages/compiler-core/src/transforms/transformElement.ts +++ b/packages/compiler-core/src/transforms/transformElement.ts @@ -665,7 +665,7 @@ export function buildProps( } // force hydration for v-bind with .prop modifier - if (isVBind && modifiers.includes('prop')) { + if (isVBind && modifiers.some(mod => mod.content === 'prop')) { patchFlag |= PatchFlags.NEED_HYDRATION } diff --git a/packages/compiler-core/src/transforms/vBind.ts b/packages/compiler-core/src/transforms/vBind.ts index 76a36145c06..233ed1e7e86 100644 --- a/packages/compiler-core/src/transforms/vBind.ts +++ b/packages/compiler-core/src/transforms/vBind.ts @@ -69,7 +69,7 @@ export const transformBind: DirectiveTransform = (dir, _node, context) => { } // .sync is replaced by v-model:arg - if (modifiers.includes('camel')) { + if (modifiers.some(mod => mod.content === 'camel')) { if (arg.type === NodeTypes.SIMPLE_EXPRESSION) { if (arg.isStatic) { arg.content = camelize(arg.content) @@ -83,10 +83,10 @@ export const transformBind: DirectiveTransform = (dir, _node, context) => { } if (!context.inSSR) { - if (modifiers.includes('prop')) { + if (modifiers.some(mod => mod.content === 'prop')) { injectPrefix(arg, '.') } - if (modifiers.includes('attr')) { + if (modifiers.some(mod => mod.content === 'attr')) { injectPrefix(arg, '^') } } diff --git a/packages/compiler-core/src/transforms/vModel.ts b/packages/compiler-core/src/transforms/vModel.ts index 60c7dc63bd1..f168c181803 100644 --- a/packages/compiler-core/src/transforms/vModel.ts +++ b/packages/compiler-core/src/transforms/vModel.ts @@ -131,6 +131,7 @@ export const transformModel: DirectiveTransform = (dir, node, context) => { // modelModifiers: { foo: true, "bar-baz": true } if (dir.modifiers.length && node.tagType === ElementTypes.COMPONENT) { const modifiers = dir.modifiers + .map(m => m.content) .map(m => (isSimpleIdentifier(m) ? m : JSON.stringify(m)) + `: true`) .join(`, `) const modifiersKey = arg diff --git a/packages/compiler-dom/src/transforms/vOn.ts b/packages/compiler-dom/src/transforms/vOn.ts index 335b84a2ed1..618d12f7153 100644 --- a/packages/compiler-dom/src/transforms/vOn.ts +++ b/packages/compiler-dom/src/transforms/vOn.ts @@ -35,7 +35,7 @@ const isKeyboardEvent = /*@__PURE__*/ makeMap( const resolveModifiers = ( key: ExpressionNode, - modifiers: string[], + modifiers: SimpleExpressionNode[], context: TransformContext, loc: SourceLocation, ) => { @@ -44,7 +44,7 @@ const resolveModifiers = ( const eventOptionModifiers = [] for (let i = 0; i < modifiers.length; i++) { - const modifier = modifiers[i] + const modifier = modifiers[i].content if ( __COMPAT__ &&