From edd49dcab40eb3faa44248772b176d5eebfd30fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A2=AB=E9=9B=A8=E6=B0=B4=E8=BF=87=E6=BB=A4=E7=9A=84?= =?UTF-8?q?=E7=A9=BA=E6=B0=94?= <958414905@qq.com> Date: Tue, 20 Oct 2020 06:08:54 +0800 Subject: [PATCH] fix(runtime-core): avoid mutating EMPTY_ARR when setting dev root (#2419) also freeze EMPTY_ARR in dev fix #2413 --- packages/runtime-core/src/componentProps.ts | 2 +- packages/runtime-core/src/componentRenderUtils.ts | 12 +++++++----- packages/runtime-core/src/vnode.ts | 2 +- packages/shared/src/index.ts | 2 +- packages/vue/__tests__/index.spec.ts | 11 +++++++++++ 5 files changed, 21 insertions(+), 8 deletions(-) diff --git a/packages/runtime-core/src/componentProps.ts b/packages/runtime-core/src/componentProps.ts index f1be9b76..47b06459 100644 --- a/packages/runtime-core/src/componentProps.ts +++ b/packages/runtime-core/src/componentProps.ts @@ -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)) { diff --git a/packages/runtime-core/src/componentRenderUtils.ts b/packages/runtime-core/src/componentRenderUtils.ts index 39f53603..a3da6e0f 100644 --- a/packages/runtime-core/src/componentRenderUtils.ts +++ b/packages/runtime-core/src/componentRenderUtils.ts @@ -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] @@ -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] diff --git a/packages/runtime-core/src/vnode.ts b/packages/runtime-core/src/vnode.ts index 8be4314d..88fca729 100644 --- a/packages/runtime-core/src/vnode.ts +++ b/packages/runtime-core/src/vnode.ts @@ -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 diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index fb355ac3..84b324be 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts @@ -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 = () => {} diff --git a/packages/vue/__tests__/index.spec.ts b/packages/vue/__tests__/index.spec.ts index 18c1c182..ae1f35bc 100644 --- a/packages/vue/__tests__/index.spec.ts +++ b/packages/vue/__tests__/index.spec.ts @@ -1,3 +1,4 @@ +import { EMPTY_ARR } from '@vue/shared' import { createApp, ref, nextTick, reactive } from '../src' describe('compiler + runtime integration', () => { @@ -281,4 +282,14 @@ describe('compiler + runtime integration', () => { await nextTick() expect(container.innerHTML).toBe(`
2
1
`) }) + + // #2413 + it('EMPTY_ARR should not change', () => { + const App = { + template: `
{{ v }}
` + } + const container = document.createElement('div') + createApp(App).mount(container) + expect(EMPTY_ARR.length).toBe(0) + }) })