}
if (!raw && !hasExtends) {
- return (comp.__props = EMPTY_ARR)
+ return (comp.__props = EMPTY_ARR as any)
}
if (isArray(raw)) {
return [vnode, undefined]
}
const rawChildren = vnode.children as VNodeArrayChildren
- const dynamicChildren = vnode.dynamicChildren as VNodeArrayChildren
+ const dynamicChildren = vnode.dynamicChildren
const childRoot = filterSingleRoot(rawChildren)
if (!childRoot) {
return [vnode, undefined]
const dynamicIndex = dynamicChildren ? dynamicChildren.indexOf(childRoot) : -1
const setRoot = (updatedRoot: VNode) => {
rawChildren[index] = updatedRoot
- if (dynamicIndex > -1) {
- dynamicChildren[dynamicIndex] = updatedRoot
- } else if (dynamicChildren && updatedRoot.patchFlag > 0) {
- dynamicChildren.push(updatedRoot)
+ if (dynamicChildren) {
+ if (dynamicIndex > -1) {
+ dynamicChildren[dynamicIndex] = updatedRoot
+ } else if (updatedRoot.patchFlag > 0) {
+ vnode.dynamicChildren = [...dynamicChildren, updatedRoot]
+ }
}
}
return [normalizeVNode(childRoot), setRoot]
true /* isBlock: prevent a block from tracking itself */
)
// save current block children on the block vnode
- vnode.dynamicChildren = currentBlock || EMPTY_ARR
+ vnode.dynamicChildren = currentBlock || (EMPTY_ARR as any)
// close block
closeBlock()
// a block is always going to be patched, so track it as a child of its
export const EMPTY_OBJ: { readonly [key: string]: any } = __DEV__
? Object.freeze({})
: {}
-export const EMPTY_ARR: [] = []
+export const EMPTY_ARR = __DEV__ ? Object.freeze([]) : []
export const NOOP = () => {}
+import { EMPTY_ARR } from '@vue/shared'
import { createApp, ref, nextTick, reactive } from '../src'
describe('compiler + runtime integration', () => {
await nextTick()
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)
+ })
})