feat(compiler-core): parse modifiers as expression to provide location data (#11819)

This commit is contained in:
山吹色御守 2024-09-05 21:00:16 +08:00 committed by GitHub
parent 7a64b6734d
commit 3f13203564
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 199 additions and 17 deletions

View File

@ -1358,7 +1358,27 @@ describe('compiler: parse', () => {
name: 'on', name: 'on',
rawName: 'v-on.enter', rawName: 'v-on.enter',
arg: undefined, 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, exp: undefined,
loc: { loc: {
start: { offset: 5, line: 1, column: 6 }, start: { offset: 5, line: 1, column: 6 },
@ -1377,7 +1397,46 @@ describe('compiler: parse', () => {
name: 'on', name: 'on',
rawName: 'v-on.enter.exact', rawName: 'v-on.enter.exact',
arg: undefined, 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, exp: undefined,
loc: { loc: {
start: { offset: 5, line: 1, column: 6 }, start: { offset: 5, line: 1, column: 6 },
@ -1406,7 +1465,46 @@ describe('compiler: parse', () => {
source: 'click', 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, exp: undefined,
loc: { loc: {
start: { offset: 5, line: 1, column: 6 }, start: { offset: 5, line: 1, column: 6 },
@ -1435,7 +1533,27 @@ describe('compiler: parse', () => {
source: '[a.b]', 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, exp: undefined,
loc: { loc: {
start: { offset: 5, line: 1, column: 6 }, start: { offset: 5, line: 1, column: 6 },
@ -1530,7 +1648,27 @@ describe('compiler: parse', () => {
source: 'a', 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: { exp: {
type: NodeTypes.SIMPLE_EXPRESSION, type: NodeTypes.SIMPLE_EXPRESSION,
content: 'b', content: 'b',
@ -1569,7 +1707,27 @@ describe('compiler: parse', () => {
source: 'a', 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: { exp: {
type: NodeTypes.SIMPLE_EXPRESSION, type: NodeTypes.SIMPLE_EXPRESSION,
content: 'b', content: 'b',
@ -1649,7 +1807,27 @@ describe('compiler: parse', () => {
source: 'a', 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: { exp: {
type: NodeTypes.SIMPLE_EXPRESSION, type: NodeTypes.SIMPLE_EXPRESSION,
content: 'b', content: 'b',

View File

@ -203,7 +203,7 @@ export interface DirectiveNode extends Node {
rawName?: string rawName?: string
exp: ExpressionNode | undefined exp: ExpressionNode | undefined
arg: ExpressionNode | undefined arg: ExpressionNode | undefined
modifiers: string[] modifiers: SimpleExpressionNode[]
/** /**
* optional property to cache the expression parse result for v-for * optional property to cache the expression parse result for v-for
*/ */

View File

@ -225,7 +225,7 @@ const tokenizer = new Tokenizer(stack, {
rawName: raw, rawName: raw,
exp: undefined, exp: undefined,
arg: undefined, arg: undefined,
modifiers: raw === '.' ? ['prop'] : [], modifiers: raw === '.' ? [createSimpleExpression('prop')] : [],
loc: getLoc(start), loc: getLoc(start),
} }
if (name === 'pre') { if (name === 'pre') {
@ -273,7 +273,8 @@ const tokenizer = new Tokenizer(stack, {
setLocEnd(arg.loc, end) setLocEnd(arg.loc, end)
} }
} else { } 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 ( if (
__COMPAT__ && __COMPAT__ &&
currentProp.name === 'bind' && currentProp.name === 'bind' &&
(syncIndex = currentProp.modifiers.indexOf('sync')) > -1 && (syncIndex = currentProp.modifiers.findIndex(
mod => mod.content === 'sync',
)) > -1 &&
checkCompatEnabled( checkCompatEnabled(
CompilerDeprecationTypes.COMPILER_V_BIND_SYNC, CompilerDeprecationTypes.COMPILER_V_BIND_SYNC,
currentOptions, currentOptions,

View File

@ -665,7 +665,7 @@ export function buildProps(
} }
// force hydration for v-bind with .prop modifier // 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 patchFlag |= PatchFlags.NEED_HYDRATION
} }

View File

@ -69,7 +69,7 @@ export const transformBind: DirectiveTransform = (dir, _node, context) => {
} }
// .sync is replaced by v-model:arg // .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.type === NodeTypes.SIMPLE_EXPRESSION) {
if (arg.isStatic) { if (arg.isStatic) {
arg.content = camelize(arg.content) arg.content = camelize(arg.content)
@ -83,10 +83,10 @@ export const transformBind: DirectiveTransform = (dir, _node, context) => {
} }
if (!context.inSSR) { if (!context.inSSR) {
if (modifiers.includes('prop')) { if (modifiers.some(mod => mod.content === 'prop')) {
injectPrefix(arg, '.') injectPrefix(arg, '.')
} }
if (modifiers.includes('attr')) { if (modifiers.some(mod => mod.content === 'attr')) {
injectPrefix(arg, '^') injectPrefix(arg, '^')
} }
} }

View File

@ -131,6 +131,7 @@ export const transformModel: DirectiveTransform = (dir, node, context) => {
// modelModifiers: { foo: true, "bar-baz": true } // modelModifiers: { foo: true, "bar-baz": true }
if (dir.modifiers.length && node.tagType === ElementTypes.COMPONENT) { if (dir.modifiers.length && node.tagType === ElementTypes.COMPONENT) {
const modifiers = dir.modifiers const modifiers = dir.modifiers
.map(m => m.content)
.map(m => (isSimpleIdentifier(m) ? m : JSON.stringify(m)) + `: true`) .map(m => (isSimpleIdentifier(m) ? m : JSON.stringify(m)) + `: true`)
.join(`, `) .join(`, `)
const modifiersKey = arg const modifiersKey = arg

View File

@ -35,7 +35,7 @@ const isKeyboardEvent = /*@__PURE__*/ makeMap(
const resolveModifiers = ( const resolveModifiers = (
key: ExpressionNode, key: ExpressionNode,
modifiers: string[], modifiers: SimpleExpressionNode[],
context: TransformContext, context: TransformContext,
loc: SourceLocation, loc: SourceLocation,
) => { ) => {
@ -44,7 +44,7 @@ const resolveModifiers = (
const eventOptionModifiers = [] const eventOptionModifiers = []
for (let i = 0; i < modifiers.length; i++) { for (let i = 0; i < modifiers.length; i++) {
const modifier = modifiers[i] const modifier = modifiers[i].content
if ( if (
__COMPAT__ && __COMPAT__ &&