Repository: vuejs/composition-api (ts)

Issue:
Incorrect check isReactive for Proxy objects
I have this code that using some DI container:
```
setup() {
   const readApi = container.resolve(ReadApi);

   return { readApi }
}
```

In my tests I replace value, provided by container, with mock object, created using jest-mock-extended. Under the box it's just a `Proxy` object.

It works well until I updated to version `rc.9`.
Here we have this change: https://github.com/vuejs/composition-api/commit/8c27d80#diff-40aa26982716adc75031925664c28d5fb4fc6dac8c7ce4d6f5122b61c1ed773eR27
And now I have such errors: `Cannot read property 'depend' of undefined`.
That's because isReactive checks for `__ob__` property of object, which is exists, but it's a mock function. So, `propValue.__ob__.dep` is undefined. Maybe you can add additional check in isReactive or just do something like `isReactive(propValue) && propValue.__ob__.dep)`

Pull request:
fix(reactivity): check type of __ob__ in isRaw and isReactive
fixes #715 

We should check the type of `__ob__` because in some cases it may be not an expected object, but, for example, a mock function, so the fact that `Boolean(!__ob__.__raw__) === true` does not necessarily indicate that the object is reactive

Patch:
diff --git a/src/apis/watch.ts b/src/apis/watch.ts
index 3f61414..c3cb5a8 100644
--- a/src/apis/watch.ts
+++ b/src/apis/watch.ts
@@ -329,7 +329,8 @@ function createWatcher(
     // The subsequent callbacks will redirect to `callback`.
     let shiftCallback = (n: any, o: any) => {
       shiftCallback = originalCallback
-      applyCb(n, o)
+      // o is undefined on the first call
+      applyCb(n, isArray(n) ? [] : o)
     }
     callback = (n: any, o: any) => {
       shiftCallback(n, o)
diff --git a/src/reactivity/reactive.ts b/src/reactivity/reactive.ts
index 38469e2..827223f 100644
--- a/src/reactivity/reactive.ts
+++ b/src/reactivity/reactive.ts
@@ -15,11 +15,15 @@ import { isRef, UnwrapRef } from './ref'
 import { rawSet, accessModifiedSet } from '../utils/sets'
 
 export function isRaw(obj: any): boolean {
-  return Boolean(obj?.__ob__ && obj.__ob__?.__raw__)
+  return Boolean(
+    obj?.__ob__ && typeof obj.__ob__ === 'object' && obj.__ob__?.__raw__
+  )
 }
 
 export function isReactive(obj: any): boolean {
-  return Boolean(obj?.__ob__ && !obj.__ob__?.__raw__)
+  return Boolean(
+    obj?.__ob__ && typeof obj.__ob__ === 'object' && !obj.__ob__?.__raw__
+  )
 }
 
 /**
diff --git a/src/reactivity/ref.ts b/src/reactivity/ref.ts
index ce8458a..32c187d 100644
--- a/src/reactivity/ref.ts
+++ b/src/reactivity/ref.ts
@@ -198,16 +198,16 @@ export function proxyRefs<T extends object>(
   for (const key of Object.keys(objectWithRefs)) {
     proxy(value, key, {
       get() {
-        if (isRef(value[key])) {
-          return value[key].value
+        if (isRef(value[RefKey][key])) {
+          return value[RefKey][key].value
         }
-        return value[key]
+        return value[RefKey][key]
       },
       set(v: unknown) {
-        if (isRef(value[key])) {
-          return (value[key].value = unref(v))
+        if (isRef(value[RefKey][key])) {
+          return (value[RefKey][key].value = unref(v))
         }
-        value[key] = unref(v)
+        value[RefKey][key] = unref(v)
       },
     })
   }


Test patch:
diff --git a/test/apis/watch.spec.js b/test/apis/watch.spec.js
index 33f5b62..eeb323e 100644
--- a/test/apis/watch.spec.js
+++ b/test/apis/watch.spec.js
@@ -457,7 +457,7 @@ describe('api/watch', () => {
         template: `<div>{{obj1.a}} {{obj2.a}}</div>`,
       }).$mount()
       expect(spy).toBeCalledTimes(1)
-      expect(spy).toHaveBeenLastCalledWith([1, 2], undefined)
+      expect(spy).toHaveBeenLastCalledWith([1, 2], [])
       obj1.a = 2
       obj2.a = 3
 
@@ -491,7 +491,7 @@ describe('api/watch', () => {
         template: `<div>{{a}} {{b}}</div>`,
       }).$mount()
       expect(spy).toBeCalledTimes(1)
-      expect(spy).toHaveBeenLastCalledWith([1, 1], undefined)
+      expect(spy).toHaveBeenLastCalledWith([1, 1], [])
       vm.a = 2
       expect(spy).toBeCalledTimes(1)
       waitForUpdate(() => {
@@ -553,7 +553,7 @@ describe('api/watch', () => {
         },
       })
       expect(spy).toBeCalledTimes(1)
-      expect(spy).toHaveBeenLastCalledWith([1, 1], undefined)
+      expect(spy).toHaveBeenLastCalledWith([1, 1], [])
       vm.a = 2
       expect(spy).toBeCalledTimes(2)
       expect(spy).toHaveBeenLastCalledWith([2, 1], [1, 1])
diff --git a/test/setup.spec.js b/test/setup.spec.js
index d63f72c..527bf89 100644
--- a/test/setup.spec.js
+++ b/test/setup.spec.js
@@ -1169,4 +1169,28 @@ describe('setup', () => {
 
     expect(warn).not.toBeCalled()
   })
+
+  it('should work with mock objects', async () => {
+    const originalProxy = new Proxy(
+      {},
+      {
+        get() {
+          return jest.fn()
+        },
+      }
+    )
+
+    const opts = {
+      template: `<div/>`,
+      setup() {
+        return {
+          proxy: originalProxy,
+        }
+      },
+    }
+    const Constructor = Vue.extend(opts).extend({})
+
+    const vm = new Vue(Constructor).$mount()
+    expect(vm.proxy).toBe(originalProxy)
+  })
 })
diff --git a/test/v3/reactivity/ref.spec.ts b/test/v3/reactivity/ref.spec.ts
index 6806224..26f8078 100644
--- a/test/v3/reactivity/ref.spec.ts
+++ b/test/v3/reactivity/ref.spec.ts
@@ -12,6 +12,7 @@ import {
   unref,
   isReactive,
   shallowRef,
+  proxyRefs,
 } from '../../../src'
 
 describe('reactivity/ref', () => {
@@ -342,4 +343,29 @@ describe('reactivity/ref', () => {
     _trigger!()
     expect(dummy).toBe(2)
   })
+
+  test('proxyRefs', () => {
+    const a = {
+      x: ref(1),
+      obj: {
+        y: ref('foo'),
+      },
+    }
+    const p = proxyRefs(a)
+    expect(p.x).toBe(1)
+    expect(p.obj.y).toBe('foo')
+
+    // @ts-expect-error
+    p.obj.y = 'bar'
+    p.x = 2
+    expect(a.x).toBe(2)
+    expect(a.obj.y).toBe('bar')
+
+    const r = reactive({ k: 'v' })
+    const s = proxyRefs(r)
+    expect(s.k).toBe('v')
+
+    r.k = 'k'
+    expect(s.k).toBe('k')
+  })
 })