From: Matt Garrett Date: Mon, 16 Sep 2024 02:49:16 +0000 (-0700) Subject: fix(watch): unwatch should be callable during SSR (#11925) X-Git-Tag: v3.5.6~12 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2d6adf78a047eed091db277ffbd9df0822fb0bdd;p=thirdparty%2Fvuejs%2Fcore.git fix(watch): unwatch should be callable during SSR (#11925) close #11924 --- diff --git a/packages/runtime-core/__tests__/apiWatch.spec.ts b/packages/runtime-core/__tests__/apiWatch.spec.ts index 7a800949ee..082d585b85 100644 --- a/packages/runtime-core/__tests__/apiWatch.spec.ts +++ b/packages/runtime-core/__tests__/apiWatch.spec.ts @@ -37,6 +37,7 @@ import { toRef, triggerRef, } from '@vue/reactivity' +import { renderToString } from '@vue/server-renderer' describe('api: watch', () => { it('effect', async () => { @@ -373,6 +374,43 @@ describe('api: watch', () => { expect(dummy).toBe(0) }) + it('stopping the watcher (SSR)', async () => { + let dummy = 0 + const count = ref(1) + const captureValue = (value: number) => { + dummy = value + } + const watchCallback = vi.fn(newValue => { + captureValue(newValue) + }) + const Comp = defineComponent({ + created() { + const getter = () => this.count + captureValue(getter()) // sets dummy to 1 + const stop = this.$watch(getter, watchCallback) + stop() + this.count = 2 // shouldn't trigger side effect + }, + render() { + return h('div', this.count) + }, + setup() { + return { count } + }, + }) + let html + html = await renderToString(h(Comp)) + // should not throw here + expect(html).toBe(`
2
`) + expect(watchCallback).not.toHaveBeenCalled() + expect(dummy).toBe(1) + await nextTick() + count.value = 3 // shouldn't trigger side effect + await nextTick() + expect(watchCallback).not.toHaveBeenCalled() + expect(dummy).toBe(1) + }) + it('stopping the watcher (with source)', async () => { const state = reactive({ count: 0 }) let dummy diff --git a/packages/runtime-core/src/apiWatch.ts b/packages/runtime-core/src/apiWatch.ts index a14823beb6..798b6e7261 100644 --- a/packages/runtime-core/src/apiWatch.ts +++ b/packages/runtime-core/src/apiWatch.ts @@ -179,11 +179,11 @@ function doWatch( // immediately watch or watchEffect baseWatchOptions.once = true } else { - return { - stop: NOOP, - resume: NOOP, - pause: NOOP, - } as WatchHandle + const watchStopHandle = () => {} + watchStopHandle.stop = NOOP + watchStopHandle.resume = NOOP + watchStopHandle.pause = NOOP + return watchStopHandle } }