From 970fe23c19ab406c728ea83a45760bc25a2a2f5d Mon Sep 17 00:00:00 2001 From: Preston Alvarado <700740+coolhome@users.noreply.github.com> Date: Fri, 31 Dec 2021 01:02:39 -0500 Subject: [PATCH] fix(useScriptTag): unload should remove script tag (#1114) --- packages/core/useScriptTag/index.test.ts | 59 ++++++++++++++++++++++++ packages/core/useScriptTag/index.ts | 8 ++-- 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/packages/core/useScriptTag/index.test.ts b/packages/core/useScriptTag/index.test.ts index 40b6e352ea12..b1e7e72a99a1 100644 --- a/packages/core/useScriptTag/index.test.ts +++ b/packages/core/useScriptTag/index.test.ts @@ -27,6 +27,33 @@ describe('useScriptTag', () => { expect(scriptTagElement()).toBeInstanceOf(HTMLScriptElement) }) + it('should re-use the same src for multiple loads', async() => { + const addChildListener = vitest.spyOn(document.head, 'appendChild') + + expect(addChildListener).not.toBeCalled() + + expect(scriptTagElement()).toBeNull() + + const vm = useSetup(() => { + const script1 = useScriptTag(src, () => {}, { immediate: false, manual: true }) + const script2 = useScriptTag(src, () => {}, { immediate: false, manual: true }) + + return { + script1, + script2, + } + }) + + await vm.script1.load(false) + await vm.script2.load(false) + + expect(vm.script1.scriptTag.value).not.toBeNull() + expect(vm.script2.scriptTag.value).not.toBeNull() + + expect(addChildListener).toBeCalledTimes(1) + expect(scriptTagElement()).toBeInstanceOf(HTMLScriptElement) + }) + it('should remove script tag on unmount', async() => { const removeChildListener = vitest.spyOn(document.head, 'removeChild') @@ -90,4 +117,36 @@ describe('useScriptTag', () => { expect(vm.scriptTag).toBeNull() }) + + it('should remove script tag on unload call after multiple loads', async() => { + const removeChildListener = vitest.spyOn(document.head, 'removeChild') + + expect(removeChildListener).not.toBeCalled() + + expect(scriptTagElement()).toBeNull() + + const vm = useSetup(() => { + const script1 = useScriptTag(src, () => {}, { immediate: false, manual: true }) + const script2 = useScriptTag(src, () => {}, { immediate: false, manual: true }) + + return { + script1, + script2, + } + }) + + // Multiple Loads + await vm.script1.load(false) + await vm.script2.load(false) + + expect(scriptTagElement()).toBeInstanceOf(HTMLScriptElement) + + vm.script1.unload() + vm.script2.unload() + + expect(vm.script1.scriptTag.value).toBeNull() + expect(vm.script2.scriptTag.value).toBeNull() + expect(removeChildListener).toBeCalledTimes(1) + expect(scriptTagElement()).toBeNull() + }) }) diff --git a/packages/core/useScriptTag/index.ts b/packages/core/useScriptTag/index.ts index 742c9885fa6e..ecbb9ce53776 100644 --- a/packages/core/useScriptTag/index.ts +++ b/packages/core/useScriptTag/index.ts @@ -156,10 +156,12 @@ export function useScriptTag( _promise = null - if (scriptTag.value) { - document.head.removeChild(scriptTag.value) + if (scriptTag.value) scriptTag.value = null - } + + const el = document.querySelector(`script[src="${src}"]`) as HTMLScriptElement + if (el) + document.head.removeChild(el) } if (immediate && !manual)