Skip to content

Commit 58b4a38

Browse files
committed
refactor(compiler-core): emit error on v-if key usage
1 parent 355c052 commit 58b4a38

File tree

4 files changed

+23
-32
lines changed

4 files changed

+23
-32
lines changed

packages/compiler-core/__tests__/transforms/__snapshots__/vIf.spec.ts.snap

-14
Original file line numberDiff line numberDiff line change
@@ -145,17 +145,3 @@ return function render(_ctx, _cache) {
145145
}
146146
}"
147147
`;
148-
149-
exports[`compiler: v-if codegen v-if with key 1`] = `
150-
"const _Vue = Vue
151-
152-
return function render(_ctx, _cache) {
153-
with (_ctx) {
154-
const { createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock, createCommentVNode: _createCommentVNode } = _Vue
155-
156-
return ok
157-
? (_openBlock(), _createBlock(\\"div\\", { key: \\"some-key\\" }))
158-
: _createCommentVNode(\\"v-if\\", true)
159-
}
160-
}"
161-
`;

packages/compiler-core/__tests__/transforms/vIf.spec.ts

+10-12
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,16 @@ describe('compiler: v-if', () => {
282282
}
283283
])
284284
})
285+
286+
test('error on user key', () => {
287+
const onError = jest.fn()
288+
parseWithIfTransform(`<div v-if="ok" :key="1" />`, { onError })
289+
expect(onError.mock.calls[0]).toMatchObject([
290+
{
291+
code: ErrorCodes.X_V_IF_KEY
292+
}
293+
])
294+
})
285295
})
286296

287297
describe('codegen', () => {
@@ -581,18 +591,6 @@ describe('compiler: v-if', () => {
581591
expect(branch1.props).toMatchObject(createObjectMatcher({ key: `[0]` }))
582592
})
583593

584-
test('v-if with key', () => {
585-
const {
586-
root,
587-
node: { codegenNode }
588-
} = parseWithIfTransform(`<div v-if="ok" key="some-key"/>`)
589-
expect(codegenNode.consequent).toMatchObject({
590-
tag: `"div"`,
591-
props: createObjectMatcher({ key: 'some-key' })
592-
})
593-
expect(generate(root).code).toMatchSnapshot()
594-
})
595-
596594
test('with comments', () => {
597595
const { node } = parseWithIfTransform(`
598596
<template v-if="ok">

packages/compiler-core/src/errors.ts

+2
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ export const enum ErrorCodes {
6363

6464
// transform errors
6565
X_V_IF_NO_EXPRESSION,
66+
X_V_IF_KEY,
6667
X_V_ELSE_NO_ADJACENT_IF,
6768
X_V_FOR_NO_EXPRESSION,
6869
X_V_FOR_MALFORMED_EXPRESSION,
@@ -135,6 +136,7 @@ export const errorMessages: { [code: number]: string } = {
135136

136137
// transform errors
137138
[ErrorCodes.X_V_IF_NO_EXPRESSION]: `v-if/v-else-if is missing expression.`,
139+
[ErrorCodes.X_V_IF_KEY]: `v-if branches must use compiler generated keys.`,
138140
[ErrorCodes.X_V_ELSE_NO_ADJACENT_IF]: `v-else/v-else-if has no adjacent v-if.`,
139141
[ErrorCodes.X_V_FOR_NO_EXPRESSION]: `v-for is missing expression.`,
140142
[ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION]: `v-for has invalid expression.`,

packages/compiler-core/src/transforms/vIf.ts

+11-6
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import {
3030
OPEN_BLOCK,
3131
TELEPORT
3232
} from '../runtimeHelpers'
33-
import { injectProp, findDir } from '../utils'
33+
import { injectProp, findDir, findProp } from '../utils'
3434
import { PatchFlags, PatchFlagNames } from '@vue/shared'
3535

3636
export const transformIf = createStructuralDirectiveTransform(
@@ -111,6 +111,11 @@ export function processIf(
111111
validateBrowserExpression(dir.exp as SimpleExpressionNode, context)
112112
}
113113

114+
const userKey = /*#__PURE__*/ findProp(node, 'key')
115+
if (userKey) {
116+
context.onError(createCompilerError(ErrorCodes.X_V_IF_KEY, userKey.loc))
117+
}
118+
114119
if (dir.name === 'if') {
115120
const branch = createIfBranch(node, dir)
116121
const ifNode: IfNode = {
@@ -175,13 +180,13 @@ function createIfBranch(node: ElementNode, dir: DirectiveNode): IfBranchNode {
175180

176181
function createCodegenNodeForBranch(
177182
branch: IfBranchNode,
178-
index: number,
183+
keyIndex: number,
179184
context: TransformContext
180185
): IfConditionalExpression | BlockCodegenNode {
181186
if (branch.condition) {
182187
return createConditionalExpression(
183188
branch.condition,
184-
createChildrenCodegenNode(branch, index, context),
189+
createChildrenCodegenNode(branch, keyIndex, context),
185190
// make sure to pass in asBlock: true so that the comment node call
186191
// closes the current block.
187192
createCallExpression(context.helper(CREATE_COMMENT), [
@@ -190,19 +195,19 @@ function createCodegenNodeForBranch(
190195
])
191196
) as IfConditionalExpression
192197
} else {
193-
return createChildrenCodegenNode(branch, index, context)
198+
return createChildrenCodegenNode(branch, keyIndex, context)
194199
}
195200
}
196201

197202
function createChildrenCodegenNode(
198203
branch: IfBranchNode,
199-
index: number,
204+
keyIndex: number,
200205
context: TransformContext
201206
): BlockCodegenNode {
202207
const { helper } = context
203208
const keyProperty = createObjectProperty(
204209
`key`,
205-
createSimpleExpression(index + '', false)
210+
createSimpleExpression(`${keyIndex}`, false)
206211
)
207212
const { children } = branch
208213
const firstChild = children[0]

0 commit comments

Comments
 (0)