From da794c4b365317d0e522fb9d343db6f7677a5961 Mon Sep 17 00:00:00 2001 From: Valentin Yushkevich Date: Wed, 14 Oct 2026 14:58:16 +0300 Subject: [PATCH 1/2] fix: support attachTo on Vue versions before 3.5 app.onUnmount, used since #2700 to remove the attachTo container, only exists since Vue 3.5, so mounting with attachTo threw on older versions while the peer range is vue 3.x. Wrap app.unmount instead. --- src/mount.ts | 18 ++++++++++++------ tests/mount.spec.ts | 21 +++++++++++++++++++++ 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/mount.ts b/src/mount.ts index 04d78c868..172390eb1 100644 --- a/src/mount.ts +++ b/src/mount.ts @@ -100,13 +100,19 @@ export function mount( } to.appendChild(el) - app.onUnmount(() => { - // The wrapper may already have been manually unmounted before auto-unmount - // runs, so the container can already be removed from its parent. - if (el.parentNode === to) { - to.removeChild(el) + // wrap app.unmount, as app.onUnmount is only available since Vue 3.5 + const unmount = app.unmount + app.unmount = () => { + try { + unmount() + } finally { + // The wrapper may already have been manually unmounted before auto-unmount + // runs, so the container can already be removed from its parent. + if (el.parentNode === to) { + to.removeChild(el) + } } - }) + } } const vm = app.mount(el) if (errorsOnMount.length) { diff --git a/tests/mount.spec.ts b/tests/mount.spec.ts index 534771003..619c68908 100644 --- a/tests/mount.spec.ts +++ b/tests/mount.spec.ts @@ -118,4 +118,25 @@ describe('mount: general tests', () => { wrapper.unmount() expect(document.body.firstChild, 'Container should be empty').toBeNull() }) + + // app.onUnmount only exists since Vue 3.5 + it('supports attachTo without app.onUnmount', () => { + const wrapper = mount(Hello, { + props: { msg: 'Hello world' }, + attachTo: document.body, + global: { + plugins: [ + { + install(app: any) { + app.onUnmount = undefined + } + } + ] + } + }) + expect(document.body.firstChild).toBeInstanceOf(HTMLDivElement) + + wrapper.unmount() + expect(document.body.firstChild).toBeNull() + }) }) From 35d458b165a1a134b47b2be6f5333821f4153e33 Mon Sep 17 00:00:00 2001 From: Valentin Yushkevich Date: Wed, 21 Oct 2026 06:55:57 +0300 Subject: [PATCH 2/2] fix: use app.onUnmount when available --- src/mount.ts | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/src/mount.ts b/src/mount.ts index 172390eb1..917489fbe 100644 --- a/src/mount.ts +++ b/src/mount.ts @@ -100,16 +100,23 @@ export function mount( } to.appendChild(el) - // wrap app.unmount, as app.onUnmount is only available since Vue 3.5 - const unmount = app.unmount - app.unmount = () => { - try { - unmount() - } finally { - // The wrapper may already have been manually unmounted before auto-unmount - // runs, so the container can already be removed from its parent. - if (el.parentNode === to) { - to.removeChild(el) + const removeContainer = () => { + // The wrapper may already have been manually unmounted before auto-unmount + // runs, so the container can already be removed from its parent. + if (el.parentNode === to) { + to.removeChild(el) + } + } + if (app.onUnmount) { + app.onUnmount(removeContainer) + } else { + // app.onUnmount is only available since Vue 3.5 + const unmount = app.unmount + app.unmount = () => { + try { + unmount() + } finally { + removeContainer() } } }