diff --git a/packages/runtime-core/__tests__/hydration.spec.ts b/packages/runtime-core/__tests__/hydration.spec.ts index 34e76100ee4..c3976a8f076 100644 --- a/packages/runtime-core/__tests__/hydration.spec.ts +++ b/packages/runtime-core/__tests__/hydration.spec.ts @@ -922,7 +922,9 @@ describe('SSR hydration', () => { ]) } } - const { container, vnode } = mountWithHydration('', () => h(Comp)) + const { container, vnode } = mountWithHydration('', () => + h(Comp) + ) expect(container.childNodes.length).toBe(3) const text = container.childNodes[1] expect(text.nodeType).toBe(3) @@ -931,6 +933,33 @@ describe('SSR hydration', () => { expect((vnode as any).component?.subTree.children[0].el).toBe(text) }) + test('app.unmount()', async () => { + const container = document.createElement('DIV') + container.innerHTML = '' + const App = defineComponent({ + setup(_, { expose }) { + const count = ref(0) + + expose({ count }) + + return () => + h('button', { + onClick: () => count.value++ + }) + } + }) + + const app = createSSRApp(App) + const vm = app.mount(container) + await nextTick() + expect((container as any)._vnode).toBeDefined() + // @ts-expect-error - expose()'d properties are not available on vm type + expect(vm.count).toBe(0) + + app.unmount() + expect((container as any)._vnode).toBe(null) + }) + describe('mismatch handling', () => { test('text node', () => { const { container } = mountWithHydration(`foo`, () => 'bar') diff --git a/packages/runtime-core/src/hydration.ts b/packages/runtime-core/src/hydration.ts index 61644184dee..3637a09b2aa 100644 --- a/packages/runtime-core/src/hydration.ts +++ b/packages/runtime-core/src/hydration.ts @@ -27,7 +27,7 @@ import { isAsyncWrapper } from './apiAsyncComponent' export type RootHydrateFunction = ( vnode: VNode, - container: Element | ShadowRoot + container: (Element | ShadowRoot) & { _vnode?: VNode } ) => void const enum DOMNodeTypes { @@ -75,11 +75,13 @@ export function createHydrationFunctions( ) patch(null, vnode, container) flushPostFlushCbs() + container._vnode = vnode return } hasMismatch = false hydrateNode(container.firstChild!, vnode, null, null, null) flushPostFlushCbs() + container._vnode = vnode if (hasMismatch && !__TEST__) { // this error should show up in production console.error(`Hydration completed but contains mismatches.`)