From d7379c7647e3222eddd18d7dad8d2520f59deb8a Mon Sep 17 00:00:00 2001 From: Evan You Date: Fri, 24 Apr 2020 12:42:46 -0400 Subject: [PATCH] fix(runtime-core): fix key/ref resolution for cloneVNode fix #1041 --- packages/runtime-core/__tests__/vnode.spec.ts | 18 ++++++++++++++ packages/runtime-core/src/vnode.ts | 24 ++++++++++++------- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/packages/runtime-core/__tests__/vnode.spec.ts b/packages/runtime-core/__tests__/vnode.spec.ts index 7408eee8..3396ed3e 100644 --- a/packages/runtime-core/__tests__/vnode.spec.ts +++ b/packages/runtime-core/__tests__/vnode.spec.ts @@ -198,6 +198,24 @@ describe('vnode', () => { expect(cloned2).toEqual(node2) expect(cloneVNode(node2)).toEqual(node2) expect(cloneVNode(node2)).toEqual(cloned2) + + // #1041 should use reoslved key/ref + expect(cloneVNode(createVNode('div', { key: 1 })).key).toBe(1) + expect(cloneVNode(createVNode('div', { key: 1 }), { key: 2 }).key).toBe(2) + expect(cloneVNode(createVNode('div'), { key: 2 }).key).toBe(2) + + // ref normalizes to [currentRenderingInstance, ref] + expect(cloneVNode(createVNode('div', { ref: 'foo' })).ref).toEqual([ + null, + 'foo' + ]) + expect( + cloneVNode(createVNode('div', { ref: 'foo' }), { ref: 'bar' }).ref + ).toEqual([null, 'bar']) + expect(cloneVNode(createVNode('div'), { ref: 'bar' }).ref).toEqual([ + null, + 'bar' + ]) }) describe('mergeProps', () => { diff --git a/packages/runtime-core/src/vnode.ts b/packages/runtime-core/src/vnode.ts index 85b04166..3e2bf518 100644 --- a/packages/runtime-core/src/vnode.ts +++ b/packages/runtime-core/src/vnode.ts @@ -312,9 +312,9 @@ function _createVNode( _isVNode: true, type, props, - key: props && props.key !== undefined ? props.key : null, + key: props && props.key != null ? props.key : null, ref: - props && props.ref !== undefined + props && props.ref != null ? [currentRenderingInstance!, props.ref] : null, scopeId: currentScopeId, @@ -362,18 +362,24 @@ export function cloneVNode( vnode: VNode, extraProps?: Data & VNodeProps ): VNode { + const props = (extraProps + ? vnode.props + ? mergeProps(vnode.props, extraProps) + : extend({}, extraProps) + : vnode.props) as any // This is intentionally NOT using spread or extend to avoid the runtime // key enumeration cost. return { _isVNode: true, type: vnode.type, - props: extraProps - ? vnode.props - ? mergeProps(vnode.props, extraProps) - : extend({}, extraProps) - : vnode.props, - key: vnode.key, - ref: vnode.ref, + props, + key: props && props.key != null ? props.key : null, + ref: + props && props.ref != null + ? isArray(props.ref) + ? props.ref + : [currentRenderingInstance!, props.ref] + : null, scopeId: vnode.scopeId, children: vnode.children, target: vnode.target,