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',
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',

View File

@ -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
*/

View File

@ -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,

View File

@ -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
}

View File

@ -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, '^')
}
}

View File

@ -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

View File

@ -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__ &&