Skip to content

Commit d531686

Browse files
committed
fix(compiler-core): elements with dynamic keys should be forced into blocks
fix #916
1 parent 2c9374d commit d531686

File tree

4 files changed

+26
-9
lines changed

4 files changed

+26
-9
lines changed

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -292,10 +292,10 @@ exports[`compiler: hoistStatic transform should NOT hoist element with dynamic k
292292
293293
return function render(_ctx, _cache) {
294294
with (_ctx) {
295-
const { createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = _Vue
295+
const { openBlock: _openBlock, createBlock: _createBlock, createVNode: _createVNode } = _Vue
296296
297297
return (_openBlock(), _createBlock(\\"div\\", null, [
298-
_createVNode(\\"div\\", { key: foo })
298+
(_openBlock(), _createBlock(\\"div\\", { key: foo }))
299299
]))
300300
}
301301
}"

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ exports[`compiler: v-for codegen keyed v-for 1`] = `
3636
3737
return function render(_ctx, _cache) {
3838
with (_ctx) {
39-
const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createBlock: _createBlock, createVNode: _createVNode } = _Vue
39+
const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createBlock: _createBlock } = _Vue
4040
4141
return (_openBlock(true), _createBlock(_Fragment, null, _renderList(items, (item) => {
4242
return (_openBlock(), _createBlock(\\"span\\", { key: item }))

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

+13
Original file line numberDiff line numberDiff line change
@@ -861,4 +861,17 @@ describe('compiler: element transform', () => {
861861
isBlock: true
862862
})
863863
})
864+
865+
// #938
866+
test('element with dynamic keys should be forced into blocks', () => {
867+
const ast = parse(`<div><div :key="foo" /></div>`)
868+
transform(ast, {
869+
nodeTransforms: [transformElement]
870+
})
871+
expect((ast as any).children[0].children[0].codegenNode).toMatchObject({
872+
type: NodeTypes.VNODE_CALL,
873+
tag: `"div"`,
874+
isBlock: true
875+
})
876+
})
864877
})

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

+10-6
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,16 @@ export const transformElement: NodeTransform = (node, context) => {
7777
let dynamicPropNames: string[] | undefined
7878
let vnodeDirectives: VNodeCall['directives']
7979

80-
// <svg> and <foreignObject> must be forced into blocks so that block
81-
// updates inside get proper isSVG flag at runtime. (#639, #643)
82-
// This is technically web-specific, but splitting the logic out of core
83-
// leads to too much unnecessary complexity.
8480
let shouldUseBlock =
85-
!isComponent && (tag === 'svg' || tag === 'foreignObject')
81+
!isComponent &&
82+
// <svg> and <foreignObject> must be forced into blocks so that block
83+
// updates inside get proper isSVG flag at runtime. (#639, #643)
84+
// This is technically web-specific, but splitting the logic out of core
85+
// leads to too much unnecessary complexity.
86+
(tag === 'svg' ||
87+
tag === 'foreignObject' ||
88+
// #938: elements with dynamic keys should be forced into blocks
89+
findProp(node, 'key', true))
8690

8791
// props
8892
if (props.length > 0) {
@@ -188,7 +192,7 @@ export const transformElement: NodeTransform = (node, context) => {
188192
vnodePatchFlag,
189193
vnodeDynamicProps,
190194
vnodeDirectives,
191-
shouldUseBlock,
195+
!!shouldUseBlock,
192196
false /* isForBlock */,
193197
node.loc
194198
)

0 commit comments

Comments
 (0)