From d531686f9154c2ef7f1d877c275df62a8d8da2a5 Mon Sep 17 00:00:00 2001 From: Evan You Date: Tue, 7 Apr 2020 18:44:21 -0400 Subject: [PATCH] fix(compiler-core): elements with dynamic keys should be forced into blocks fix #916 --- .../__snapshots__/hoistStatic.spec.ts.snap | 4 ++-- .../transforms/__snapshots__/vFor.spec.ts.snap | 2 +- .../transforms/transformElement.spec.ts | 13 +++++++++++++ .../src/transforms/transformElement.ts | 16 ++++++++++------ 4 files changed, 26 insertions(+), 9 deletions(-) diff --git a/packages/compiler-core/__tests__/transforms/__snapshots__/hoistStatic.spec.ts.snap b/packages/compiler-core/__tests__/transforms/__snapshots__/hoistStatic.spec.ts.snap index de021a5e25a..c94cf2905b7 100644 --- a/packages/compiler-core/__tests__/transforms/__snapshots__/hoistStatic.spec.ts.snap +++ b/packages/compiler-core/__tests__/transforms/__snapshots__/hoistStatic.spec.ts.snap @@ -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 })) ])) } }" diff --git a/packages/compiler-core/__tests__/transforms/__snapshots__/vFor.spec.ts.snap b/packages/compiler-core/__tests__/transforms/__snapshots__/vFor.spec.ts.snap index 27367a94314..870922105c0 100644 --- a/packages/compiler-core/__tests__/transforms/__snapshots__/vFor.spec.ts.snap +++ b/packages/compiler-core/__tests__/transforms/__snapshots__/vFor.spec.ts.snap @@ -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 })) diff --git a/packages/compiler-core/__tests__/transforms/transformElement.spec.ts b/packages/compiler-core/__tests__/transforms/transformElement.spec.ts index 14cbb39e0bf..6bdef0db0ce 100644 --- a/packages/compiler-core/__tests__/transforms/transformElement.spec.ts +++ b/packages/compiler-core/__tests__/transforms/transformElement.spec.ts @@ -861,4 +861,17 @@ describe('compiler: element transform', () => { isBlock: true }) }) + + // #938 + test('element with dynamic keys should be forced into blocks', () => { + const ast = parse(`
`) + transform(ast, { + nodeTransforms: [transformElement] + }) + expect((ast as any).children[0].children[0].codegenNode).toMatchObject({ + type: NodeTypes.VNODE_CALL, + tag: `"div"`, + isBlock: true + }) + }) }) diff --git a/packages/compiler-core/src/transforms/transformElement.ts b/packages/compiler-core/src/transforms/transformElement.ts index 8e2a7ac64d1..8caff936e63 100644 --- a/packages/compiler-core/src/transforms/transformElement.ts +++ b/packages/compiler-core/src/transforms/transformElement.ts @@ -77,12 +77,16 @@ export const transformElement: NodeTransform = (node, context) => { let dynamicPropNames: string[] | undefined let vnodeDirectives: VNodeCall['directives'] - // and 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 && + // and 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 )