]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(runtime-core): should not track deps in pre flush watcher callbacks
authorEvan You <yyx990803@gmail.com>
Fri, 26 Mar 2021 19:52:45 +0000 (15:52 -0400)
committerEvan You <yyx990803@gmail.com>
Fri, 26 Mar 2021 19:52:49 +0000 (15:52 -0400)
fix #2728

packages/runtime-core/__tests__/apiWatch.spec.ts
packages/runtime-core/src/renderer.ts

index 30248072a9b2cb5d522aa507c631b9845c0c9be2..4a0b7a900c0ae7c2ac8e58c73d6a406cab372c06 100644 (file)
@@ -877,4 +877,42 @@ describe('api: watch', () => {
     expect(instance).toBeDefined()
     expect(source).toHaveBeenCalledWith(instance)
   })
+
+  // #2728
+  test('pre watcher callbacks should not track dependencies', async () => {
+    const a = ref(0)
+    const b = ref(0)
+    const updated = jest.fn()
+
+    const Child = defineComponent({
+      props: ['a'],
+      updated,
+      watch: {
+        a() {
+          b.value
+        }
+      },
+      render() {
+        return h('div', this.a)
+      }
+    })
+
+    const Parent = defineComponent({
+      render() {
+        return h(Child, { a: a.value })
+      }
+    })
+
+    const root = nodeOps.createElement('div')
+    createApp(Parent).mount(root)
+
+    a.value++
+    await nextTick()
+    expect(updated).toHaveBeenCalledTimes(1)
+
+    b.value++
+    await nextTick()
+    // should not track b as dependency of Child
+    expect(updated).toHaveBeenCalledTimes(1)
+  })
 })
index 4f67869b658f3e89500e70f1edf4dae6aee7669a..4375dcdbf1030035bb64928df2f087becdde8ae3 100644 (file)
@@ -48,7 +48,14 @@ import {
   flushPreFlushCbs,
   SchedulerCb
 } from './scheduler'
-import { effect, stop, ReactiveEffectOptions, isRef } from '@vue/reactivity'
+import {
+  effect,
+  stop,
+  ReactiveEffectOptions,
+  isRef,
+  pauseTracking,
+  resetTracking
+} from '@vue/reactivity'
 import { updateProps } from './componentProps'
 import { updateSlots } from './componentSlots'
 import { pushWarningContext, popWarningContext, warn } from './warning'
@@ -1567,9 +1574,11 @@ function baseCreateRenderer(
     updateProps(instance, nextVNode.props, prevProps, optimized)
     updateSlots(instance, nextVNode.children)
 
+    pauseTracking()
     // props update may have triggered pre-flush watchers.
     // flush them before the render update.
     flushPreFlushCbs(undefined, instance.update)
+    resetTracking()
   }
 
   const patchChildren: PatchChildrenFn = (