]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(runtime-core/watch): trigger watcher with undefined as initial value (#687)
authorEduardo San Martin Morote <posva@users.noreply.github.com>
Tue, 4 Feb 2020 14:59:04 +0000 (15:59 +0100)
committerGitHub <noreply@github.com>
Tue, 4 Feb 2020 14:59:04 +0000 (09:59 -0500)
Fix #683

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

index ad8f4787145db4eb6c95dfc7a4bc910fb8d9c22d..82a4ad368111ad519cab2061e49304f928e53ae9 100644 (file)
@@ -27,6 +27,33 @@ describe('api: watch', () => {
     expect(dummy).toBe(1)
   })
 
+  it('triggers when initial value is null', async () => {
+    const state = ref(null)
+    const spy = jest.fn()
+    watch(() => state.value, spy)
+    await nextTick()
+    expect(spy).toHaveBeenCalled()
+  })
+
+  it('triggers when initial value is undefined', async () => {
+    const state = ref()
+    const spy = jest.fn()
+    watch(() => state.value, spy)
+    await nextTick()
+    expect(spy).toHaveBeenCalled()
+    state.value = 3
+    await nextTick()
+    expect(spy).toHaveBeenCalledTimes(2)
+    // testing if undefined can trigger the watcher
+    state.value = undefined
+    await nextTick()
+    expect(spy).toHaveBeenCalledTimes(3)
+    // it shouldn't trigger if the same value is set
+    state.value = undefined
+    await nextTick()
+    expect(spy).toHaveBeenCalledTimes(3)
+  })
+
   it('watching single source: getter', async () => {
     const state = reactive({ count: 0 })
     let dummy
index 74acbfd59f24eb1d5fc640a5d1811d2ce0c3c8d4..c4bcdd58f0dcddef667aec01cd0a6e4d4bb9978c 100644 (file)
@@ -61,6 +61,9 @@ export type StopHandle = () => void
 
 const invoke = (fn: Function) => fn()
 
+// initial value for watchers to trigger on undefined initial values
+const INITIAL_WATCHER_VALUE = {}
+
 // overload #1: simple effect
 export function watch(effect: WatchEffect, options?: WatchOptions): StopHandle
 
@@ -153,7 +156,7 @@ function doWatch(
     }
   }
 
-  let oldValue = isArray(source) ? [] : undefined
+  let oldValue = isArray(source) ? [] : INITIAL_WATCHER_VALUE
   const applyCb = cb
     ? () => {
         if (instance && instance.isUnmounted) {
@@ -167,7 +170,8 @@ function doWatch(
           }
           callWithAsyncErrorHandling(cb, instance, ErrorCodes.WATCH_CALLBACK, [
             newValue,
-            oldValue,
+            // pass undefined as the old value when it's changed for the first time
+            oldValue === INITIAL_WATCHER_VALUE ? undefined : oldValue,
             registerCleanup
           ])
           oldValue = newValue