]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(ssr): ensure app can be unmounted when created with createSSRApp() (#5992)
authorThorsten Lünborg <t.luenborg@googlemail.com>
Tue, 24 May 2022 12:30:40 +0000 (14:30 +0200)
committerGitHub <noreply@github.com>
Tue, 24 May 2022 12:30:40 +0000 (08:30 -0400)
fix #5990

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

index 34e76100ee4991181e16aa31648bdabe0e75d499..c3976a8f07688614c7941280b61919208e83e6af 100644 (file)
@@ -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 = '<button></button>'
+    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')
index 61644184dee7908559da065096633cb8265946a8..3637a09b2aaa6c54911a10bc294d58b9cbeb9f06 100644 (file)
@@ -27,7 +27,7 @@ import { isAsyncWrapper } from './apiAsyncComponent'
 
 export type RootHydrateFunction = (
   vnode: VNode<Node, Element>,
-  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.`)