From dcf2458fa84d7573273b0306aaabcf28ee859622 Mon Sep 17 00:00:00 2001 From: Evan You Date: Fri, 24 Apr 2020 12:18:51 -0400 Subject: [PATCH] fix(runtime-core): fix dynamic node tracking in dynamic component that resolves to plain elements fix #1039 --- packages/runtime-core/__tests__/vnode.spec.ts | 21 +++++++++++++++++++ packages/runtime-core/src/vnode.ts | 16 +++++++++----- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/packages/runtime-core/__tests__/vnode.spec.ts b/packages/runtime-core/__tests__/vnode.spec.ts index b8993456..7408eee8 100644 --- a/packages/runtime-core/__tests__/vnode.spec.ts +++ b/packages/runtime-core/__tests__/vnode.spec.ts @@ -337,6 +337,27 @@ describe('vnode', () => { ])) expect(vnode.dynamicChildren).toStrictEqual([vnode1]) }) + + // #1039 + // {{ bar }} + // - content is compiled as slot + // - dynamic component reoslves to plain element, but as a block + // - block creation disables its own tracking, accidentally causing the + // slot content (called during the block node creation) to be missed + test('element block should track normalized slot children', () => { + const hoist = createVNode('div') + let vnode1 + const vnode = (openBlock(), + createBlock('div', null, { + default: () => { + return [ + hoist, + (vnode1 = createVNode('div', null, 'text', PatchFlags.TEXT)) + ] + } + })) + expect(vnode.dynamicChildren).toStrictEqual([vnode1]) + }) }) describe('transformVNodeArgs', () => { diff --git a/packages/runtime-core/src/vnode.ts b/packages/runtime-core/src/vnode.ts index 8f494472..85b04166 100644 --- a/packages/runtime-core/src/vnode.ts +++ b/packages/runtime-core/src/vnode.ts @@ -177,10 +177,14 @@ export function createBlock( patchFlag?: number, dynamicProps?: string[] ): VNode { - // avoid a block with patchFlag tracking itself - shouldTrack-- - const vnode = createVNode(type, props, children, patchFlag, dynamicProps) - shouldTrack++ + const vnode = createVNode( + type, + props, + children, + patchFlag, + dynamicProps, + true /* isBlock: prevent a block from tracking itself */ + ) // save current block children on the block vnode vnode.dynamicChildren = currentBlock || EMPTY_ARR // close block @@ -244,7 +248,8 @@ function _createVNode( props: (Data & VNodeProps) | null = null, children: unknown = null, patchFlag: number = 0, - dynamicProps: string[] | null = null + dynamicProps: string[] | null = null, + isBlockNode = false ): VNode { if (!type) { if (__DEV__) { @@ -337,6 +342,7 @@ function _createVNode( // the next vnode so that it can be properly unmounted later. if ( shouldTrack > 0 && + !isBlockNode && currentBlock && // the EVENTS flag is only for hydration and if it is the only flag, the // vnode should not be considered dynamic due to handler caching.