import { ErrorCodes } from '../../src/errors'
import { type CompilerOptions, generate } from '../../src'
import { FRAGMENT, RENDER_LIST, RENDER_SLOT } from '../../src/runtimeHelpers'
-import { PatchFlags } from '@vue/shared'
+import { PatchFlagNames, PatchFlags } from '@vue/shared'
import { createObjectMatcher, genFlagText } from '../testUtils'
export function parseWithForTransform(
})
expect(generate(root).code).toMatchSnapshot()
})
+
+ test('template v-for key w/ :key shorthand on div', () => {
+ const {
+ node: { codegenNode },
+ } = parseWithForTransform('<div v-for="key in keys" :key>test</div>')
+ expect(codegenNode.patchFlag).toBe(
+ `${PatchFlags.KEYED_FRAGMENT} /* ${PatchFlagNames[PatchFlags.KEYED_FRAGMENT]} */`,
+ )
+ })
+
+ test('template v-for key w/ :key shorthand on template injected to the child', () => {
+ const {
+ node: { codegenNode },
+ } = parseWithForTransform(
+ '<template v-for="key in keys" :key><div>test</div></template>',
+ )
+ expect(assertSharedCodegen(codegenNode, true)).toMatchObject({
+ source: { content: `keys` },
+ params: [{ content: `key` }],
+ innerVNodeCall: {
+ type: NodeTypes.VNODE_CALL,
+ tag: `"div"`,
+ props: createObjectMatcher({
+ key: '[key]',
+ }),
+ },
+ })
+ })
})
})
-import type { DirectiveTransform } from '../transform'
+import type { DirectiveTransform, TransformContext } from '../transform'
import {
+ type DirectiveNode,
type ExpressionNode,
NodeTypes,
type SimpleExpressionNode,
}
}
- const propName = camelize((arg as SimpleExpressionNode).content)
- exp = dir.exp = createSimpleExpression(propName, false, arg.loc)
- if (!__BROWSER__) {
- exp = dir.exp = processExpression(exp, context)
- }
+ transformBindShorthand(dir, context)
+ exp = dir.exp!
}
if (arg.type !== NodeTypes.SIMPLE_EXPRESSION) {
}
}
+export const transformBindShorthand = (
+ dir: DirectiveNode,
+ context: TransformContext,
+) => {
+ const arg = dir.arg!
+
+ const propName = camelize((arg as SimpleExpressionNode).content)
+ dir.exp = createSimpleExpression(propName, false, arg.loc)
+ if (!__BROWSER__) {
+ dir.exp = processExpression(dir.exp, context)
+ }
+}
+
const injectPrefix = (arg: ExpressionNode, prefix: string) => {
if (arg.type === NodeTypes.SIMPLE_EXPRESSION) {
if (arg.isStatic) {
import { processExpression } from './transformExpression'
import { validateBrowserExpression } from '../validateExpression'
import { PatchFlagNames, PatchFlags } from '@vue/shared'
+import { transformBindShorthand } from './vBind'
export const transformFor = createStructuralDirectiveTransform(
'for',
]) as ForRenderListExpression
const isTemplate = isTemplateNode(node)
const memo = findDir(node, 'memo')
- const keyProp = findProp(node, `key`)
+ const keyProp = findProp(node, `key`, false, true)
+ if (keyProp && keyProp.type === NodeTypes.DIRECTIVE && !keyProp.exp) {
+ // resolve :key shorthand #10882
+ transformBindShorthand(keyProp, context)
+ }
const keyExp =
keyProp &&
(keyProp.type === NodeTypes.ATTRIBUTE
- ? createSimpleExpression(keyProp.value!.content, true)
- : keyProp.exp!)
- const keyProperty = keyProp ? createObjectProperty(`key`, keyExp!) : null
+ ? keyProp.value
+ ? createSimpleExpression(keyProp.value.content, true)
+ : undefined
+ : keyProp.exp)
+ const keyProperty =
+ keyProp && keyExp ? createObjectProperty(`key`, keyExp) : null
if (!__BROWSER__ && isTemplate) {
// #2085 / #5288 process :key and v-memo expressions need to be