From 0b9142eb5cd3998956a943e84d998b8cb25aa5fb Mon Sep 17 00:00:00 2001 From: edison1105 Date: Sat, 17 Jun 2023 16:50:26 +0800 Subject: [PATCH 01/10] fix(runtime-core): filter single root for nested DEV_ROOT_FRAGMENT --- packages/runtime-core/src/componentRenderUtils.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/runtime-core/src/componentRenderUtils.ts b/packages/runtime-core/src/componentRenderUtils.ts index d9de968a074..b16d7e57a17 100644 --- a/packages/runtime-core/src/componentRenderUtils.ts +++ b/packages/runtime-core/src/componentRenderUtils.ts @@ -290,6 +290,11 @@ export function filterSingleRoot( return } } + + if (singleRoot && singleRoot.patchFlag & PatchFlags.DEV_ROOT_FRAGMENT) { + return filterSingleRoot(singleRoot.children as VNodeArrayChildren) + } + return singleRoot } From d8587025770cd79a0fc07576f027b97040c6cc66 Mon Sep 17 00:00:00 2001 From: edison1105 Date: Sat, 17 Jun 2023 17:09:11 +0800 Subject: [PATCH 02/10] chore: improve code --- packages/runtime-core/src/componentRenderUtils.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/runtime-core/src/componentRenderUtils.ts b/packages/runtime-core/src/componentRenderUtils.ts index b16d7e57a17..11ab7d49609 100644 --- a/packages/runtime-core/src/componentRenderUtils.ts +++ b/packages/runtime-core/src/componentRenderUtils.ts @@ -291,7 +291,11 @@ export function filterSingleRoot( } } - if (singleRoot && singleRoot.patchFlag & PatchFlags.DEV_ROOT_FRAGMENT) { + if ( + singleRoot && + singleRoot.patchFlag > 0 && + singleRoot.patchFlag & PatchFlags.DEV_ROOT_FRAGMENT + ) { return filterSingleRoot(singleRoot.children as VNodeArrayChildren) } From e18b794215de63b43746cd99b704b939fc0fe5d4 Mon Sep 17 00:00:00 2001 From: edison1105 Date: Sat, 17 Jun 2023 18:22:32 +0800 Subject: [PATCH 03/10] test: add test case --- .../runtime-core/__tests__/scopeId.spec.ts | 61 ++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/packages/runtime-core/__tests__/scopeId.spec.ts b/packages/runtime-core/__tests__/scopeId.spec.ts index cdbb81c4191..4c89df7998b 100644 --- a/packages/runtime-core/__tests__/scopeId.spec.ts +++ b/packages/runtime-core/__tests__/scopeId.spec.ts @@ -6,9 +6,19 @@ import { renderSlot, withScopeId, pushScopeId, - popScopeId + popScopeId, + ref, + defineComponent, + openBlock, + createBlock, + Fragment, + createCommentVNode, + mergeProps, + createVNode, + nextTick } from '@vue/runtime-test' import { withCtx } from '../src/componentRenderContext' +import { PatchFlags } from '@vue/shared' describe('scopeId runtime support', () => { test('should attach scopeId', () => { @@ -184,6 +194,55 @@ describe('scopeId runtime support', () => { expect(serializeInner(root)).toBe(`
`) }) + + test('should inherit scopeId through nested DEV_ROOT_FRAGMENT with inheritAttrs: false', async () => { + const Parent = { + __scopeId: 'parent', + render() { + return h(Child, { class: 'foo' }) + } + } + + const ok = ref(true) + const Child = defineComponent({ + inheritAttrs: false, + render() { + return ( + openBlock(), + createBlock( + Fragment, + null, + [ + createCommentVNode('comment1'), + ok.value + ? (openBlock(), createBlock('div', { key: 0 }, 'div1')) + : (openBlock(), + createBlock( + Fragment, + { key: 1 }, + [ + createCommentVNode('comment2'), + createVNode('div', null, 'div2') + ], + PatchFlags.STABLE_FRAGMENT | PatchFlags.DEV_ROOT_FRAGMENT + )) + ], + PatchFlags.STABLE_FRAGMENT | PatchFlags.DEV_ROOT_FRAGMENT + ) + ) + } + }) + + const root = nodeOps.createElement('div') + render(h(Parent), root) + expect(serializeInner(root)).toBe(`
div1
`) + + ok.value = false + await nextTick() + expect(serializeInner(root)).toBe( + `
div2
` + ) + }) }) describe('backwards compat with <=3.0.7', () => { From ba71195c9e1d241c640c0d7909bf7ecb8df62d00 Mon Sep 17 00:00:00 2001 From: edison1105 Date: Sun, 18 Jun 2023 14:52:59 +0800 Subject: [PATCH 04/10] chore: clean --- packages/runtime-core/__tests__/scopeId.spec.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/runtime-core/__tests__/scopeId.spec.ts b/packages/runtime-core/__tests__/scopeId.spec.ts index 4c89df7998b..bcb7c3c28d3 100644 --- a/packages/runtime-core/__tests__/scopeId.spec.ts +++ b/packages/runtime-core/__tests__/scopeId.spec.ts @@ -13,7 +13,6 @@ import { createBlock, Fragment, createCommentVNode, - mergeProps, createVNode, nextTick } from '@vue/runtime-test' From c5ce3d02d9982ed46c26ef7b5a649bf3ba07e9a7 Mon Sep 17 00:00:00 2001 From: edison1105 Date: Wed, 13 Sep 2023 21:08:37 +0800 Subject: [PATCH 05/10] chore: improve code --- packages/runtime-core/src/componentRenderUtils.ts | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/runtime-core/src/componentRenderUtils.ts b/packages/runtime-core/src/componentRenderUtils.ts index 11ab7d49609..7aa58fe0702 100644 --- a/packages/runtime-core/src/componentRenderUtils.ts +++ b/packages/runtime-core/src/componentRenderUtils.ts @@ -284,6 +284,12 @@ export function filterSingleRoot( return } else { singleRoot = child + if ( + singleRoot.patchFlag > 0 && + singleRoot.patchFlag & PatchFlags.DEV_ROOT_FRAGMENT + ) { + return filterSingleRoot(singleRoot.children as VNodeArrayChildren) + } } } } else { @@ -291,14 +297,6 @@ export function filterSingleRoot( } } - if ( - singleRoot && - singleRoot.patchFlag > 0 && - singleRoot.patchFlag & PatchFlags.DEV_ROOT_FRAGMENT - ) { - return filterSingleRoot(singleRoot.children as VNodeArrayChildren) - } - return singleRoot } From 86c9a909f0033cb35e68c80fea153402774fdc1b Mon Sep 17 00:00:00 2001 From: edison1105 Date: Wed, 13 Sep 2023 21:09:51 +0800 Subject: [PATCH 06/10] chore: improve code --- packages/runtime-core/src/componentRenderUtils.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/runtime-core/src/componentRenderUtils.ts b/packages/runtime-core/src/componentRenderUtils.ts index 7aa58fe0702..d13df8c109e 100644 --- a/packages/runtime-core/src/componentRenderUtils.ts +++ b/packages/runtime-core/src/componentRenderUtils.ts @@ -296,7 +296,6 @@ export function filterSingleRoot( return } } - return singleRoot } From 8a01c3e486157cee5c84604cf08bce0ae588dddd Mon Sep 17 00:00:00 2001 From: daiwei Date: Thu, 14 Sep 2023 09:10:45 +0800 Subject: [PATCH 07/10] chore: add more case --- .../rendererAttrsFallthrough.spec.ts | 53 +++++++++++++++++++ .../runtime-core/src/componentRenderUtils.ts | 12 ++++- 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/packages/runtime-core/__tests__/rendererAttrsFallthrough.spec.ts b/packages/runtime-core/__tests__/rendererAttrsFallthrough.spec.ts index 1de05b67b44..10ef8ec61a4 100644 --- a/packages/runtime-core/__tests__/rendererAttrsFallthrough.spec.ts +++ b/packages/runtime-core/__tests__/rendererAttrsFallthrough.spec.ts @@ -19,6 +19,7 @@ import { withModifiers } from '@vue/runtime-dom' import { PatchFlags } from '@vue/shared' +import { createElementBlock, createElementVNode } from '../src' describe('attribute fallthrough', () => { it('should allow attrs to fallthrough', async () => { @@ -673,6 +674,58 @@ describe('attribute fallthrough', () => { expect(click).toHaveBeenCalled() }) + it('should support fallthrough for nested fragments', async () => { + const toggle = ref(false) + + const Child = { + setup() { + return () => ( + openBlock(), + createElementBlock( + Fragment, + null, + [ + createCommentVNode(' comment A '), + toggle.value + ? (openBlock(), createElementBlock('span', { key: 0 }, 'Foo')) + : (openBlock(), + createElementBlock( + Fragment, + { key: 1 }, + [ + createCommentVNode(' comment B '), + createElementVNode('div', null, 'Bar') + ], + PatchFlags.STABLE_FRAGMENT | PatchFlags.DEV_ROOT_FRAGMENT + )) + ], + PatchFlags.STABLE_FRAGMENT | PatchFlags.DEV_ROOT_FRAGMENT + ) + ) + } + } + + const Root = { + setup() { + return () => (openBlock(), createBlock(Child, { class: 'red' })) + } + } + + const root = document.createElement('div') + document.body.appendChild(root) + render(h(Root), root) + + expect(root.innerHTML).toBe( + `
Bar
` + ) + + toggle.value = true + await nextTick() + expect(root.innerHTML).toBe( + `Foo` + ) + }) + // #1989 it('should not fallthrough v-model listeners with corresponding declared prop', () => { let textFoo = '' diff --git a/packages/runtime-core/src/componentRenderUtils.ts b/packages/runtime-core/src/componentRenderUtils.ts index d13df8c109e..af44b6d8205 100644 --- a/packages/runtime-core/src/componentRenderUtils.ts +++ b/packages/runtime-core/src/componentRenderUtils.ts @@ -251,10 +251,16 @@ export function renderComponentRoot( const getChildRoot = (vnode: VNode): [VNode, SetRootFn] => { const rawChildren = vnode.children as VNodeArrayChildren const dynamicChildren = vnode.dynamicChildren - const childRoot = filterSingleRoot(rawChildren) + const childRoot = filterSingleRoot(rawChildren, false) if (!childRoot) { return [vnode, undefined] + } else if ( + childRoot.patchFlag > 0 && + childRoot.patchFlag & PatchFlags.DEV_ROOT_FRAGMENT + ) { + return getChildRoot(childRoot) } + const index = rawChildren.indexOf(childRoot) const dynamicIndex = dynamicChildren ? dynamicChildren.indexOf(childRoot) : -1 const setRoot: SetRootFn = (updatedRoot: VNode) => { @@ -271,7 +277,8 @@ const getChildRoot = (vnode: VNode): [VNode, SetRootFn] => { } export function filterSingleRoot( - children: VNodeArrayChildren + children: VNodeArrayChildren, + recursion: boolean = true ): VNode | undefined { let singleRoot for (let i = 0; i < children.length; i++) { @@ -285,6 +292,7 @@ export function filterSingleRoot( } else { singleRoot = child if ( + recursion && singleRoot.patchFlag > 0 && singleRoot.patchFlag & PatchFlags.DEV_ROOT_FRAGMENT ) { From 554b59a4eb084590f989b117ac65467bf372a4d9 Mon Sep 17 00:00:00 2001 From: daiwei Date: Thu, 14 Sep 2023 09:15:35 +0800 Subject: [PATCH 08/10] chore: add more case --- .../runtime-core/__tests__/rendererAttrsFallthrough.spec.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/runtime-core/__tests__/rendererAttrsFallthrough.spec.ts b/packages/runtime-core/__tests__/rendererAttrsFallthrough.spec.ts index 10ef8ec61a4..f7b141ef88f 100644 --- a/packages/runtime-core/__tests__/rendererAttrsFallthrough.spec.ts +++ b/packages/runtime-core/__tests__/rendererAttrsFallthrough.spec.ts @@ -15,11 +15,12 @@ import { createBlock, FunctionalComponent, createCommentVNode, + createElementBlock, + createElementVNode, Fragment, withModifiers } from '@vue/runtime-dom' import { PatchFlags } from '@vue/shared' -import { createElementBlock, createElementVNode } from '../src' describe('attribute fallthrough', () => { it('should allow attrs to fallthrough', async () => { From 0ccbe6ec1311136412f67832457847a24fe4b147 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Fri, 12 Jan 2024 13:02:24 +0000 Subject: [PATCH 09/10] [autofix.ci] apply automated fixes --- .../rendererAttrsFallthrough.spec.ts | 22 +++++++------- .../runtime-core/__tests__/scopeId.spec.ts | 30 +++++++++---------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/packages/runtime-core/__tests__/rendererAttrsFallthrough.spec.ts b/packages/runtime-core/__tests__/rendererAttrsFallthrough.spec.ts index 1962cc33a80..bb79c912ce7 100644 --- a/packages/runtime-core/__tests__/rendererAttrsFallthrough.spec.ts +++ b/packages/runtime-core/__tests__/rendererAttrsFallthrough.spec.ts @@ -4,19 +4,19 @@ // using DOM renderer because this case is mostly DOM-specific import { + Fragment, Fragment, type FunctionalComponent, createBlock, createCommentVNode, + createElementBlock, + createElementVNode, defineComponent, h, mergeProps, nextTick, onUpdated, openBlock, - createElementBlock, - createElementVNode, - Fragment, ref, render, withModifiers, @@ -696,21 +696,21 @@ describe('attribute fallthrough', () => { { key: 1 }, [ createCommentVNode(' comment B '), - createElementVNode('div', null, 'Bar') + createElementVNode('div', null, 'Bar'), ], - PatchFlags.STABLE_FRAGMENT | PatchFlags.DEV_ROOT_FRAGMENT - )) + PatchFlags.STABLE_FRAGMENT | PatchFlags.DEV_ROOT_FRAGMENT, + )), ], - PatchFlags.STABLE_FRAGMENT | PatchFlags.DEV_ROOT_FRAGMENT + PatchFlags.STABLE_FRAGMENT | PatchFlags.DEV_ROOT_FRAGMENT, ) ) - } + }, } const Root = { setup() { return () => (openBlock(), createBlock(Child, { class: 'red' })) - } + }, } const root = document.createElement('div') @@ -718,13 +718,13 @@ describe('attribute fallthrough', () => { render(h(Root), root) expect(root.innerHTML).toBe( - `
Bar
` + `
Bar
`, ) toggle.value = true await nextTick() expect(root.innerHTML).toBe( - `Foo` + `Foo`, ) }) diff --git a/packages/runtime-core/__tests__/scopeId.spec.ts b/packages/runtime-core/__tests__/scopeId.spec.ts index 80d409a485c..08753e023a1 100644 --- a/packages/runtime-core/__tests__/scopeId.spec.ts +++ b/packages/runtime-core/__tests__/scopeId.spec.ts @@ -1,20 +1,20 @@ import { + Fragment, + createBlock, + createCommentVNode, + createVNode, + defineComponent, h, + nextTick, nodeOps, + openBlock, popScopeId, pushScopeId, + ref, render, renderSlot, serializeInner, withScopeId, - ref, - defineComponent, - openBlock, - createBlock, - Fragment, - createCommentVNode, - createVNode, - nextTick } from '@vue/runtime-test' import { withCtx } from '../src/componentRenderContext' import { PatchFlags } from '@vue/shared' @@ -199,7 +199,7 @@ describe('scopeId runtime support', () => { __scopeId: 'parent', render() { return h(Child, { class: 'foo' }) - } + }, } const ok = ref(true) @@ -221,15 +221,15 @@ describe('scopeId runtime support', () => { { key: 1 }, [ createCommentVNode('comment2'), - createVNode('div', null, 'div2') + createVNode('div', null, 'div2'), ], - PatchFlags.STABLE_FRAGMENT | PatchFlags.DEV_ROOT_FRAGMENT - )) + PatchFlags.STABLE_FRAGMENT | PatchFlags.DEV_ROOT_FRAGMENT, + )), ], - PatchFlags.STABLE_FRAGMENT | PatchFlags.DEV_ROOT_FRAGMENT + PatchFlags.STABLE_FRAGMENT | PatchFlags.DEV_ROOT_FRAGMENT, ) ) - } + }, }) const root = nodeOps.createElement('div') @@ -239,7 +239,7 @@ describe('scopeId runtime support', () => { ok.value = false await nextTick() expect(serializeInner(root)).toBe( - `
div2
` + `
div2
`, ) }) }) From 11378064e7ea1b21e3cefde3ab8b969ce2ee20ca Mon Sep 17 00:00:00 2001 From: Evan You Date: Fri, 12 Jan 2024 21:46:05 +0800 Subject: [PATCH 10/10] refactor: minor tweaks + add dev flags --- .../runtime-core/__tests__/rendererAttrsFallthrough.spec.ts | 3 +-- packages/runtime-core/src/componentRenderUtils.ts | 6 ++++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/runtime-core/__tests__/rendererAttrsFallthrough.spec.ts b/packages/runtime-core/__tests__/rendererAttrsFallthrough.spec.ts index bb79c912ce7..79e2867ad69 100644 --- a/packages/runtime-core/__tests__/rendererAttrsFallthrough.spec.ts +++ b/packages/runtime-core/__tests__/rendererAttrsFallthrough.spec.ts @@ -4,7 +4,6 @@ // using DOM renderer because this case is mostly DOM-specific import { - Fragment, Fragment, type FunctionalComponent, createBlock, @@ -676,7 +675,7 @@ describe('attribute fallthrough', () => { expect(click).toHaveBeenCalled() }) - it('should support fallthrough for nested fragments', async () => { + it('should support fallthrough for nested dev root fragments', async () => { const toggle = ref(false) const Child = { diff --git a/packages/runtime-core/src/componentRenderUtils.ts b/packages/runtime-core/src/componentRenderUtils.ts index 174324c6e19..4b83c699031 100644 --- a/packages/runtime-core/src/componentRenderUtils.ts +++ b/packages/runtime-core/src/componentRenderUtils.ts @@ -270,6 +270,7 @@ const getChildRoot = (vnode: VNode): [VNode, SetRootFn] => { if (!childRoot) { return [vnode, undefined] } else if ( + __DEV__ && childRoot.patchFlag > 0 && childRoot.patchFlag & PatchFlags.DEV_ROOT_FRAGMENT ) { @@ -293,7 +294,7 @@ const getChildRoot = (vnode: VNode): [VNode, SetRootFn] => { export function filterSingleRoot( children: VNodeArrayChildren, - recursion: boolean = true, + recurse = true, ): VNode | undefined { let singleRoot for (let i = 0; i < children.length; i++) { @@ -307,7 +308,8 @@ export function filterSingleRoot( } else { singleRoot = child if ( - recursion && + __DEV__ && + recurse && singleRoot.patchFlag > 0 && singleRoot.patchFlag & PatchFlags.DEV_ROOT_FRAGMENT ) {