]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(compiler-core): elements with dynamic keys should be forced into blocks
authorEvan You <yyx990803@gmail.com>
Tue, 7 Apr 2020 22:44:21 +0000 (18:44 -0400)
committerEvan You <yyx990803@gmail.com>
Tue, 7 Apr 2020 22:44:21 +0000 (18:44 -0400)
fix #916

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

index de021a5e25a6e71708fd165ff2d6deafb4a8d66c..c94cf2905b799e69962be6a41fa046ceecac05b2 100644 (file)
@@ -292,10 +292,10 @@ exports[`compiler: hoistStatic transform should NOT hoist element with dynamic k
 
 return function render(_ctx, _cache) {
   with (_ctx) {
-    const { createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = _Vue
+    const { openBlock: _openBlock, createBlock: _createBlock, createVNode: _createVNode } = _Vue
 
     return (_openBlock(), _createBlock(\\"div\\", null, [
-      _createVNode(\\"div\\", { key: foo })
+      (_openBlock(), _createBlock(\\"div\\", { key: foo }))
     ]))
   }
 }"
index 27367a943141c69513c1bac372bdb493be25723f..870922105c05f4589bd235914929e6f9fdf1c192 100644 (file)
@@ -36,7 +36,7 @@ exports[`compiler: v-for codegen keyed v-for 1`] = `
 
 return function render(_ctx, _cache) {
   with (_ctx) {
-    const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createBlock: _createBlock, createVNode: _createVNode } = _Vue
+    const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createBlock: _createBlock } = _Vue
 
     return (_openBlock(true), _createBlock(_Fragment, null, _renderList(items, (item) => {
       return (_openBlock(), _createBlock(\\"span\\", { key: item }))
index 14cbb39e0bf201bdadc9f7b703e026c22cc1576b..6bdef0db0ce1e088caefc54799c4e5817c251423 100644 (file)
@@ -861,4 +861,17 @@ describe('compiler: element transform', () => {
       isBlock: true
     })
   })
+
+  // #938
+  test('element with dynamic keys should be forced into blocks', () => {
+    const ast = parse(`<div><div :key="foo" /></div>`)
+    transform(ast, {
+      nodeTransforms: [transformElement]
+    })
+    expect((ast as any).children[0].children[0].codegenNode).toMatchObject({
+      type: NodeTypes.VNODE_CALL,
+      tag: `"div"`,
+      isBlock: true
+    })
+  })
 })
index 8e2a7ac64d1366391677e85db80d9d7c34a89f61..8caff936e630488b3dc014d0145a9c39f5d77c32 100644 (file)
@@ -77,12 +77,16 @@ export const transformElement: NodeTransform = (node, context) => {
     let dynamicPropNames: string[] | undefined
     let vnodeDirectives: VNodeCall['directives']
 
-    // <svg> and <foreignObject> must be forced into blocks so that block
-    // updates inside get proper isSVG flag at runtime. (#639, #643)
-    // This is technically web-specific, but splitting the logic out of core
-    // leads to too much unnecessary complexity.
     let shouldUseBlock =
-      !isComponent && (tag === 'svg' || tag === 'foreignObject')
+      !isComponent &&
+      // <svg> and <foreignObject> must be forced into blocks so that block
+      // updates inside get proper isSVG flag at runtime. (#639, #643)
+      // This is technically web-specific, but splitting the logic out of core
+      // leads to too much unnecessary complexity.
+      (tag === 'svg' ||
+        tag === 'foreignObject' ||
+        // #938: elements with dynamic keys should be forced into blocks
+        findProp(node, 'key', true))
 
     // props
     if (props.length > 0) {
@@ -188,7 +192,7 @@ export const transformElement: NodeTransform = (node, context) => {
       vnodePatchFlag,
       vnodeDynamicProps,
       vnodeDirectives,
-      shouldUseBlock,
+      !!shouldUseBlock,
       false /* isForBlock */,
       node.loc
     )