diff --git a/packages/reactivity/__tests__/computed.spec.ts b/packages/reactivity/__tests__/computed.spec.ts index 6f5d7197157..d0c4dc499da 100644 --- a/packages/reactivity/__tests__/computed.spec.ts +++ b/packages/reactivity/__tests__/computed.spec.ts @@ -1,3 +1,4 @@ +import { h, nextTick, nodeOps, render, serializeInner } from '@vue/runtime-test' import { type DebuggerEvent, ITERATE_KEY, @@ -470,15 +471,24 @@ describe('reactivity/computed', () => { expect(c2.effect._dirtyLevel).toBe(DirtyLevels.NotDirty) }) - it('should work when chained(ref+computed)', () => { - const value = ref(0) + it('should be not dirty after deps mutate (mutate deps in computed)', async () => { + const state = reactive({}) const consumer = computed(() => { - value.value++ - return 'foo' - }) - const provider = computed(() => value.value + consumer.value) - expect(provider.value).toBe('0foo') - expect(provider.effect._dirtyLevel).toBe(DirtyLevels.Dirty) - expect(provider.value).toBe('1foo') + if (!('a' in state)) state.a = 1 + return state.a + }) + const Comp = { + setup: () => { + nextTick().then(() => { + state.a = 2 + }) + return () => consumer.value + }, + } + const root = nodeOps.createElement('div') + render(h(Comp), root) + await nextTick() + await nextTick() + expect(serializeInner(root)).toBe(`2`) }) }) diff --git a/packages/reactivity/src/effect.ts b/packages/reactivity/src/effect.ts index e8a3d996752..6d13f3b9977 100644 --- a/packages/reactivity/src/effect.ts +++ b/packages/reactivity/src/effect.ts @@ -295,7 +295,10 @@ export function triggerEffects( // when recurse effect is running, dep map could have outdated items continue } - if (effect._dirtyLevel < dirtyLevel) { + if ( + effect._dirtyLevel < dirtyLevel && + !(effect._runnings && !effect.allowRecurse) + ) { const lastDirtyLevel = effect._dirtyLevel effect._dirtyLevel = dirtyLevel if (lastDirtyLevel === DirtyLevels.NotDirty) {