]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(reactivity): ensure computed is invalidated before other effects
authorEvan You <yyx990803@gmail.com>
Fri, 15 Apr 2022 08:43:17 +0000 (16:43 +0800)
committerEvan You <yyx990803@gmail.com>
Fri, 15 Apr 2022 08:43:17 +0000 (16:43 +0800)
fix #5720

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

index a3efc8c854a9c304a9e56a8cae48b51767fa9654..3e4dead83719399c650143a61f3ad5f3660335dd 100644 (file)
@@ -170,6 +170,23 @@ describe('reactivity/computed', () => {
     expect(dummy).toBe(-1)
   })
 
+  // #5720
+  it('should invalidate before non-computed effects', () => {
+    let plusOneValues: number[] = []
+    const n = ref(0)
+    const plusOne = computed(() => n.value + 1)
+    effect(() => {
+      n.value
+      plusOneValues.push(plusOne.value)
+    })
+    // access plusOne, causing it to be non-dirty
+    plusOne.value
+    // mutate n
+    n.value++
+    // on the 2nd run, plusOne.value should have already updated.
+    expect(plusOneValues).toMatchObject([1, 2, 2])
+  })
+
   it('should warn if trying to set a readonly computed', () => {
     const n = ref(1)
     const plusOne = computed(() => n.value + 1)
index 77312eaa2cf6cb496b9e4fd751e5c4d676ea5fe3..34b53eb8fef103354e236eea8f2b508208a15df2 100644 (file)
@@ -348,16 +348,31 @@ export function triggerEffects(
   debuggerEventExtraInfo?: DebuggerEventExtraInfo
 ) {
   // spread into array for stabilization
-  for (const effect of isArray(dep) ? dep : [...dep]) {
-    if (effect !== activeEffect || effect.allowRecurse) {
-      if (__DEV__ && effect.onTrigger) {
-        effect.onTrigger(extend({ effect }, debuggerEventExtraInfo))
-      }
-      if (effect.scheduler) {
-        effect.scheduler()
-      } else {
-        effect.run()
-      }
+  const effects = isArray(dep) ? dep : [...dep]
+  for (const effect of effects) {
+    if (effect.computed) {
+      triggerEffect(effect, debuggerEventExtraInfo)
+    }
+  }
+  for (const effect of effects) {
+    if (!effect.computed) {
+      triggerEffect(effect, debuggerEventExtraInfo)
+    }
+  }
+}
+
+function triggerEffect(
+  effect: ReactiveEffect,
+  debuggerEventExtraInfo?: DebuggerEventExtraInfo
+) {
+  if (effect !== activeEffect || effect.allowRecurse) {
+    if (__DEV__ && effect.onTrigger) {
+      effect.onTrigger(extend({ effect }, debuggerEventExtraInfo))
+    }
+    if (effect.scheduler) {
+      effect.scheduler()
+    } else {
+      effect.run()
     }
   }
 }