fix(runtime-core): avoid mutating EMPTY_ARR when setting dev root (#2419)
also freeze EMPTY_ARR in dev fix #2413
This commit is contained in:
		
							parent
							
								
									e894caf731
								
							
						
					
					
						commit
						edd49dcab4
					
				@ -378,7 +378,7 @@ export function normalizePropsOptions(
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (!raw && !hasExtends) {
 | 
					  if (!raw && !hasExtends) {
 | 
				
			||||||
    return (comp.__props = EMPTY_ARR)
 | 
					    return (comp.__props = EMPTY_ARR as any)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (isArray(raw)) {
 | 
					  if (isArray(raw)) {
 | 
				
			||||||
 | 
				
			|||||||
@ -226,7 +226,7 @@ const getChildRoot = (
 | 
				
			|||||||
    return [vnode, undefined]
 | 
					    return [vnode, undefined]
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  const rawChildren = vnode.children as VNodeArrayChildren
 | 
					  const rawChildren = vnode.children as VNodeArrayChildren
 | 
				
			||||||
  const dynamicChildren = vnode.dynamicChildren as VNodeArrayChildren
 | 
					  const dynamicChildren = vnode.dynamicChildren
 | 
				
			||||||
  const childRoot = filterSingleRoot(rawChildren)
 | 
					  const childRoot = filterSingleRoot(rawChildren)
 | 
				
			||||||
  if (!childRoot) {
 | 
					  if (!childRoot) {
 | 
				
			||||||
    return [vnode, undefined]
 | 
					    return [vnode, undefined]
 | 
				
			||||||
@ -235,10 +235,12 @@ const getChildRoot = (
 | 
				
			|||||||
  const dynamicIndex = dynamicChildren ? dynamicChildren.indexOf(childRoot) : -1
 | 
					  const dynamicIndex = dynamicChildren ? dynamicChildren.indexOf(childRoot) : -1
 | 
				
			||||||
  const setRoot = (updatedRoot: VNode) => {
 | 
					  const setRoot = (updatedRoot: VNode) => {
 | 
				
			||||||
    rawChildren[index] = updatedRoot
 | 
					    rawChildren[index] = updatedRoot
 | 
				
			||||||
 | 
					    if (dynamicChildren) {
 | 
				
			||||||
      if (dynamicIndex > -1) {
 | 
					      if (dynamicIndex > -1) {
 | 
				
			||||||
        dynamicChildren[dynamicIndex] = updatedRoot
 | 
					        dynamicChildren[dynamicIndex] = updatedRoot
 | 
				
			||||||
    } else if (dynamicChildren && updatedRoot.patchFlag > 0) {
 | 
					      } else if (updatedRoot.patchFlag > 0) {
 | 
				
			||||||
      dynamicChildren.push(updatedRoot)
 | 
					        vnode.dynamicChildren = [...dynamicChildren, updatedRoot]
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return [normalizeVNode(childRoot), setRoot]
 | 
					  return [normalizeVNode(childRoot), setRoot]
 | 
				
			||||||
 | 
				
			|||||||
@ -243,7 +243,7 @@ export function createBlock(
 | 
				
			|||||||
    true /* isBlock: prevent a block from tracking itself */
 | 
					    true /* isBlock: prevent a block from tracking itself */
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
  // save current block children on the block vnode
 | 
					  // save current block children on the block vnode
 | 
				
			||||||
  vnode.dynamicChildren = currentBlock || EMPTY_ARR
 | 
					  vnode.dynamicChildren = currentBlock || (EMPTY_ARR as any)
 | 
				
			||||||
  // close block
 | 
					  // close block
 | 
				
			||||||
  closeBlock()
 | 
					  closeBlock()
 | 
				
			||||||
  // a block is always going to be patched, so track it as a child of its
 | 
					  // a block is always going to be patched, so track it as a child of its
 | 
				
			||||||
 | 
				
			|||||||
@ -28,7 +28,7 @@ export const babelParserDefaultPlugins = [
 | 
				
			|||||||
export const EMPTY_OBJ: { readonly [key: string]: any } = __DEV__
 | 
					export const EMPTY_OBJ: { readonly [key: string]: any } = __DEV__
 | 
				
			||||||
  ? Object.freeze({})
 | 
					  ? Object.freeze({})
 | 
				
			||||||
  : {}
 | 
					  : {}
 | 
				
			||||||
export const EMPTY_ARR: [] = []
 | 
					export const EMPTY_ARR = __DEV__ ? Object.freeze([]) : []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const NOOP = () => {}
 | 
					export const NOOP = () => {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					import { EMPTY_ARR } from '@vue/shared'
 | 
				
			||||||
import { createApp, ref, nextTick, reactive } from '../src'
 | 
					import { createApp, ref, nextTick, reactive } from '../src'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
describe('compiler + runtime integration', () => {
 | 
					describe('compiler + runtime integration', () => {
 | 
				
			||||||
@ -281,4 +282,14 @@ describe('compiler + runtime integration', () => {
 | 
				
			|||||||
    await nextTick()
 | 
					    await nextTick()
 | 
				
			||||||
    expect(container.innerHTML).toBe(`<div>2<div>1</div></div>`)
 | 
					    expect(container.innerHTML).toBe(`<div>2<div>1</div></div>`)
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // #2413
 | 
				
			||||||
 | 
					  it('EMPTY_ARR should not change', () => {
 | 
				
			||||||
 | 
					    const App = {
 | 
				
			||||||
 | 
					      template: `<div v-for="v of ['a']">{{ v }}</div>`
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const container = document.createElement('div')
 | 
				
			||||||
 | 
					    createApp(App).mount(container)
 | 
				
			||||||
 | 
					    expect(EMPTY_ARR.length).toBe(0)
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user