Skip to content

Commit

Permalink
fix(runtime-core): fix fragment update inside de-opt slots
Browse files Browse the repository at this point in the history
fix #3881
  • Loading branch information
yyx990803 committed Jun 4, 2021
1 parent 71f7c25 commit 5bce2ae
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 2 deletions.
62 changes: 61 additions & 1 deletion packages/runtime-core/__tests__/rendererOptimizedMode.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ import {
onBeforeUnmount,
createTextVNode,
SetupContext,
createApp
createApp,
FunctionalComponent,
renderList
} from '@vue/runtime-test'
import { PatchFlags, SlotFlags } from '@vue/shared'
import { SuspenseImpl } from '../src/components/Suspense'
Expand Down Expand Up @@ -821,4 +823,62 @@ describe('renderer: optimized mode', () => {
await nextTick()
expect(inner(root)).toBe('<div><div>true</div></div>')
})

// #3881
// root cause: fragment inside a compiled slot passed to component which
// programmatically invokes the slot. The entire slot should de-opt but
// the fragment was incorretly put in optimized mode which causes it to skip
// updates for its inner components.
test('fragments inside programmatically invoked compiled slot should de-opt properly', async () => {
const Parent: FunctionalComponent = (_, { slots }) => slots.default!()
const Dummy = () => 'dummy'

const toggle = ref(true)
const force = ref(0)

const app = createApp({
render() {
if (!toggle.value) {
return null
}
return h(
Parent,
{ n: force.value },
{
default: withCtx(
() => [
createVNode('ul', null, [
(openBlock(),
createBlock(
Fragment,
null,
renderList(1, item => {
return createVNode('li', null, [createVNode(Dummy)])
}),
64 /* STABLE_FRAGMENT */
))
])
],
undefined,
true
),
_: 1 /* STABLE */
}
)
}
})

app.mount(root)

// force a patch
force.value++
await nextTick()
expect(inner(root)).toBe(`<ul><li>dummy</li></ul>`)

// unmount
toggle.value = false
await nextTick()
// should successfully unmount without error
expect(inner(root)).toBe(`<!---->`)
})
})
2 changes: 1 addition & 1 deletion packages/runtime-core/src/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1170,7 +1170,7 @@ function baseCreateRenderer(
const fragmentEndAnchor = (n2.anchor = n1 ? n1.anchor : hostCreateText(''))!

let { patchFlag, dynamicChildren, slotScopeIds: fragmentSlotScopeIds } = n2
if (patchFlag > 0) {
if (dynamicChildren) {
optimized = true
}

Expand Down

0 comments on commit 5bce2ae

Please sign in to comment.