]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(reactivity): fix recursive sync watcher on computed edge case
authorEvan You <evan@vuejs.org>
Thu, 26 Sep 2024 10:38:02 +0000 (18:38 +0800)
committerEvan You <evan@vuejs.org>
Thu, 26 Sep 2024 10:38:13 +0000 (18:38 +0800)
close #12033
close #12037

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

index b3d18e19f71205181594de041ca40458ccd78f66..f333d7c06e033002606f5100138dc0c9620d6e24 100644 (file)
@@ -4,6 +4,7 @@ import {
   WatchErrorCodes,
   type WatchOptions,
   type WatchScheduler,
+  computed,
   onWatcherCleanup,
   ref,
   watch,
@@ -209,4 +210,23 @@ describe('watch', () => {
     source.value++
     expect(dummy).toBe(1)
   })
+
+  // #12033
+  test('recursive sync watcher on computed', () => {
+    const r = ref(0)
+    const c = computed(() => r.value)
+
+    watch(c, v => {
+      if (v > 1) {
+        r.value--
+      }
+    })
+
+    expect(r.value).toBe(0)
+    expect(c.value).toBe(0)
+
+    r.value = 10
+    expect(r.value).toBe(1)
+    expect(c.value).toBe(1)
+  })
 })
index b681df85cdb727b7e55dcff7204cc80efdc3e08e..15693ee39b45a11c4a1625b0ec3564d26839baff 100644 (file)
@@ -260,11 +260,14 @@ export function endBatch(): void {
   let error: unknown
   while (batchedSub) {
     let e: Subscriber | undefined = batchedSub
-    batchedSub = undefined
+    let next: Subscriber | undefined
     while (e) {
-      const next: Subscriber | undefined = e.next
-      e.next = undefined
       e.flags &= ~EffectFlags.NOTIFIED
+      e = e.next
+    }
+    e = batchedSub
+    batchedSub = undefined
+    while (e) {
       if (e.flags & EffectFlags.ACTIVE) {
         try {
           // ACTIVE flag is effect-only
@@ -273,6 +276,8 @@ export function endBatch(): void {
           if (!error) error = err
         }
       }
+      next = e.next
+      e.next = undefined
       e = next
     }
   }