Skip to content

Commit d4d3319

Browse files
authored
fix(ssr): ensure app can be unmounted when created with createSSRApp() (#5992)
fix #5990
1 parent 160d5df commit d4d3319

File tree

2 files changed

+33
-2
lines changed

2 files changed

+33
-2
lines changed

packages/runtime-core/__tests__/hydration.spec.ts

+30-1
Original file line numberDiff line numberDiff line change
@@ -922,7 +922,9 @@ describe('SSR hydration', () => {
922922
])
923923
}
924924
}
925-
const { container, vnode } = mountWithHydration('<!--[--><!--]-->', () => h(Comp))
925+
const { container, vnode } = mountWithHydration('<!--[--><!--]-->', () =>
926+
h(Comp)
927+
)
926928
expect(container.childNodes.length).toBe(3)
927929
const text = container.childNodes[1]
928930
expect(text.nodeType).toBe(3)
@@ -931,6 +933,33 @@ describe('SSR hydration', () => {
931933
expect((vnode as any).component?.subTree.children[0].el).toBe(text)
932934
})
933935

936+
test('app.unmount()', async () => {
937+
const container = document.createElement('DIV')
938+
container.innerHTML = '<button></button>'
939+
const App = defineComponent({
940+
setup(_, { expose }) {
941+
const count = ref(0)
942+
943+
expose({ count })
944+
945+
return () =>
946+
h('button', {
947+
onClick: () => count.value++
948+
})
949+
}
950+
})
951+
952+
const app = createSSRApp(App)
953+
const vm = app.mount(container)
954+
await nextTick()
955+
expect((container as any)._vnode).toBeDefined()
956+
// @ts-expect-error - expose()'d properties are not available on vm type
957+
expect(vm.count).toBe(0)
958+
959+
app.unmount()
960+
expect((container as any)._vnode).toBe(null)
961+
})
962+
934963
describe('mismatch handling', () => {
935964
test('text node', () => {
936965
const { container } = mountWithHydration(`foo`, () => 'bar')

packages/runtime-core/src/hydration.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import { isAsyncWrapper } from './apiAsyncComponent'
2727

2828
export type RootHydrateFunction = (
2929
vnode: VNode<Node, Element>,
30-
container: Element | ShadowRoot
30+
container: (Element | ShadowRoot) & { _vnode?: VNode }
3131
) => void
3232

3333
const enum DOMNodeTypes {
@@ -75,11 +75,13 @@ export function createHydrationFunctions(
7575
)
7676
patch(null, vnode, container)
7777
flushPostFlushCbs()
78+
container._vnode = vnode
7879
return
7980
}
8081
hasMismatch = false
8182
hydrateNode(container.firstChild!, vnode, null, null, null)
8283
flushPostFlushCbs()
84+
container._vnode = vnode
8385
if (hasMismatch && !__TEST__) {
8486
// this error should show up in production
8587
console.error(`Hydration completed but contains mismatches.`)

0 commit comments

Comments
 (0)