Skip to content

Commit

Permalink
fix(runtime-core): avoid mutating EMPTY_ARR when setting dev root (#2419
Browse files Browse the repository at this point in the history
)

also freeze EMPTY_ARR in dev

fix #2413
  • Loading branch information
zhangzhonghe authored Oct 19, 2020
1 parent e894caf commit edd49dc
Show file tree
Hide file tree
Showing 5 changed files with 21 additions and 8 deletions.
2 changes: 1 addition & 1 deletion packages/runtime-core/src/componentProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ export function normalizePropsOptions(
}

if (!raw && !hasExtends) {
return (comp.__props = EMPTY_ARR)
return (comp.__props = EMPTY_ARR as any)
}

if (isArray(raw)) {
Expand Down
12 changes: 7 additions & 5 deletions packages/runtime-core/src/componentRenderUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ const getChildRoot = (
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]
Expand All @@ -235,10 +235,12 @@ const getChildRoot = (
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]
Expand Down
2 changes: 1 addition & 1 deletion packages/runtime-core/src/vnode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ export function createBlock(
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
Expand Down
2 changes: 1 addition & 1 deletion packages/shared/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const babelParserDefaultPlugins = [
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 = () => {}

Expand Down
11 changes: 11 additions & 0 deletions packages/vue/__tests__/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { EMPTY_ARR } from '@vue/shared'
import { createApp, ref, nextTick, reactive } from '../src'

describe('compiler + runtime integration', () => {
Expand Down Expand Up @@ -281,4 +282,14 @@ 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)
})
})

0 comments on commit edd49dc

Please sign in to comment.