fix(compiler-core): elements with dynamic keys should be forced into blocks
fix #916
This commit is contained in:
		
							parent
							
								
									2c9374dd91
								
							
						
					
					
						commit
						d531686f91
					
				@ -292,10 +292,10 @@ exports[`compiler: hoistStatic transform should NOT hoist element with dynamic k
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
return function render(_ctx, _cache) {
 | 
					return function render(_ctx, _cache) {
 | 
				
			||||||
  with (_ctx) {
 | 
					  with (_ctx) {
 | 
				
			||||||
    const { createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = _Vue
 | 
					    const { openBlock: _openBlock, createBlock: _createBlock, createVNode: _createVNode } = _Vue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (_openBlock(), _createBlock(\\"div\\", null, [
 | 
					    return (_openBlock(), _createBlock(\\"div\\", null, [
 | 
				
			||||||
      _createVNode(\\"div\\", { key: foo })
 | 
					      (_openBlock(), _createBlock(\\"div\\", { key: foo }))
 | 
				
			||||||
    ]))
 | 
					    ]))
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}"
 | 
					}"
 | 
				
			||||||
 | 
				
			|||||||
@ -36,7 +36,7 @@ exports[`compiler: v-for codegen keyed v-for 1`] = `
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
return function render(_ctx, _cache) {
 | 
					return function render(_ctx, _cache) {
 | 
				
			||||||
  with (_ctx) {
 | 
					  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(true), _createBlock(_Fragment, null, _renderList(items, (item) => {
 | 
				
			||||||
      return (_openBlock(), _createBlock(\\"span\\", { key: item }))
 | 
					      return (_openBlock(), _createBlock(\\"span\\", { key: item }))
 | 
				
			||||||
 | 
				
			|||||||
@ -861,4 +861,17 @@ describe('compiler: element transform', () => {
 | 
				
			|||||||
      isBlock: true
 | 
					      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
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 | 
				
			|||||||
@ -77,12 +77,16 @@ export const transformElement: NodeTransform = (node, context) => {
 | 
				
			|||||||
    let dynamicPropNames: string[] | undefined
 | 
					    let dynamicPropNames: string[] | undefined
 | 
				
			||||||
    let vnodeDirectives: VNodeCall['directives']
 | 
					    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 =
 | 
					    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
 | 
					    // props
 | 
				
			||||||
    if (props.length > 0) {
 | 
					    if (props.length > 0) {
 | 
				
			||||||
@ -188,7 +192,7 @@ export const transformElement: NodeTransform = (node, context) => {
 | 
				
			|||||||
      vnodePatchFlag,
 | 
					      vnodePatchFlag,
 | 
				
			||||||
      vnodeDynamicProps,
 | 
					      vnodeDynamicProps,
 | 
				
			||||||
      vnodeDirectives,
 | 
					      vnodeDirectives,
 | 
				
			||||||
      shouldUseBlock,
 | 
					      !!shouldUseBlock,
 | 
				
			||||||
      false /* isForBlock */,
 | 
					      false /* isForBlock */,
 | 
				
			||||||
      node.loc
 | 
					      node.loc
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user