]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(reactivity): fix regression for computed with mutation (#10119)
authorDoctor Wu <44631608+Doctor-wu@users.noreply.github.com>
Mon, 15 Jan 2024 15:38:57 +0000 (23:38 +0800)
committerGitHub <noreply@github.com>
Mon, 15 Jan 2024 15:38:57 +0000 (23:38 +0800)
close #10114

packages/reactivity/__tests__/computed.spec.ts
packages/reactivity/src/effect.ts

index 6f5d7197157b9e2048b7decf487e09958c3a7b94..d0c4dc499daa1239eaa7279cb0dfe473eb867cbd 100644 (file)
@@ -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<any>({})
     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`)
   })
 })
index e8a3d996752d8597862b42780a852c4a78f95fd2..6d13f3b9977cbd0b0b82191c44587802b082609c 100644 (file)
@@ -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) {