From: Jürg Lehni Date: Thu, 5 Sep 2024 10:54:30 +0000 (+0200) Subject: fix(reactivity): prevent endless recursion in computed getters (#11797) X-Git-Tag: v3.5.2~7 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=716275d1b1d2383d8ef0306fcd94558d4d9170f2;p=thirdparty%2Fvuejs%2Fcore.git fix(reactivity): prevent endless recursion in computed getters (#11797) --- diff --git a/packages/reactivity/__tests__/computed.spec.ts b/packages/reactivity/__tests__/computed.spec.ts index c3409eee77..31daef559a 100644 --- a/packages/reactivity/__tests__/computed.spec.ts +++ b/packages/reactivity/__tests__/computed.spec.ts @@ -1,4 +1,6 @@ import { + type TestElement, + defineComponent, h, nextTick, nodeOps, @@ -6,6 +8,7 @@ import { onUnmounted, render, serializeInner, + triggerEvent, } from '@vue/runtime-test' import { type DebuggerEvent, @@ -958,4 +961,46 @@ describe('reactivity/computed', () => { newValue: 2, }) }) + + test('should prevent endless recursion in self-referencing computed getters', async () => { + const Comp = defineComponent({ + data() { + return { + counter: 0, + } + }, + + computed: { + message(): string { + if (this.counter === 0) { + this.counter++ + return this.message + } else { + return `Step ${this.counter}` + } + }, + }, + + render() { + return [ + h( + 'button', + { + onClick: () => { + this.counter++ + }, + }, + 'Step', + ), + h('p', this.message), + ] + }, + }) + const root = nodeOps.createElement('div') + render(h(Comp), root) + expect(serializeInner(root)).toBe(`

`) + triggerEvent(root.children[1] as TestElement, 'click') + await nextTick() + expect(serializeInner(root)).toBe(`

Step 2

`) + }) }) diff --git a/packages/reactivity/src/dep.ts b/packages/reactivity/src/dep.ts index 4ce73ac995..6d938cbc25 100644 --- a/packages/reactivity/src/dep.ts +++ b/packages/reactivity/src/dep.ts @@ -46,7 +46,7 @@ export class Dep { } track(debugInfo?: DebuggerEventExtraInfo): Link | undefined { - if (!activeSub || !shouldTrack) { + if (!activeSub || !shouldTrack || activeSub === this.computed) { return }