Repository: vuejs/composition-api (ts)

Issue:
Bug props in composition-api beta 14
```
export default {
  props: {
    filter: {
      type: Object,
      default: function() {
        return {
          c1: 'c1',
        }
      },
    },
  },
  setup(props) {
    console.log('props is: ', isRef(props), isReactive(props))
    watch(props, () => {  // error 
      console.log(props)
    }
  }
}
```
beta11:  props is: false true
beta14:  props is: false false //  watch --> error


Pull request:
fix: reactive for props
fix #534

Patch:
diff --git a/src/apis/watch.ts b/src/apis/watch.ts
index 1d505c3..4e1724a 100644
--- a/src/apis/watch.ts
+++ b/src/apis/watch.ts
@@ -182,7 +182,7 @@ function createVueWatcher(
 }
 
 // We have to monkeypatch the teardown function so Vue will run
-// runCleanup() when it tears down the watcher on unmmount.
+// runCleanup() when it tears down the watcher on unmounted.
 function patchWatcherTeardown(watcher: VueWatcher, runCleanup: () => void) {
   const _teardown = watcher.teardown
   watcher.teardown = function (...args) {
diff --git a/src/mixin.ts b/src/mixin.ts
index a70c131..a199ecf 100644
--- a/src/mixin.ts
+++ b/src/mixin.ts
@@ -23,7 +23,7 @@ import {
   resolveScopedSlots,
   asVmProperty,
 } from './utils/instance'
-import { PropsReactive } from './utils/symbols'
+import { createObserver } from './reactivity/reactive'
 
 export function mixin(Vue: VueConstructor) {
   Vue.mixin({
@@ -83,7 +83,7 @@ export function mixin(Vue: VueConstructor) {
     const ctx = createSetupContext(vm)
 
     // fake reactive for `toRefs(props)`
-    def(props, PropsReactive, true)
+    def(props, '__ob__', createObserver())
 
     // resolve scopedSlots and slots to functions
     resolveScopedSlots(vm, ctx.slots)
diff --git a/src/reactivity/reactive.ts b/src/reactivity/reactive.ts
index 585f304..857dc20 100644
--- a/src/reactivity/reactive.ts
+++ b/src/reactivity/reactive.ts
@@ -119,6 +119,10 @@ function observe<T>(obj: T): T {
   return observed
 }
 
+export function createObserver() {
+  return observe<any>({}).__ob__ || {}
+}
+
 export function shallowReactive<T extends object = any>(obj: T): T
 export function shallowReactive(obj: any): any {
   if (__DEV__ && !obj) {
@@ -255,7 +259,7 @@ export function markRaw<T extends object>(obj: T): T {
   }
 
   // set the vue observable flag at obj
-  const ob = (observe({}) as any).__ob__
+  const ob = createObserver()
   ob.__raw__ = true
   def(obj, '__ob__', ob)
 
diff --git a/src/reactivity/ref.ts b/src/reactivity/ref.ts
index b68a2fb..fdcd636 100644
--- a/src/reactivity/ref.ts
+++ b/src/reactivity/ref.ts
@@ -1,5 +1,5 @@
 import { Data } from '../component'
-import { RefKey, PropsReactive } from '../utils/symbols'
+import { RefKey } from '../utils/symbols'
 import { proxy, isPlainObject, warn } from '../utils'
 import { reactive, isReactive, shallowReactive } from './reactive'
 import { readonlySet } from '../utils/sets'
@@ -114,16 +114,13 @@ export function ref(raw?: unknown) {
 export function isRef<T>(value: any): value is Ref<T> {
   return value instanceof RefImpl
 }
-function isPropObject(obj: unknown) {
-  return obj && typeof obj === 'object' && PropsReactive in obj
-}
 
 export function unref<T>(ref: T): T extends Ref<infer V> ? V : T {
   return isRef(ref) ? (ref.value as any) : ref
 }
 
 export function toRefs<T extends Data = Data>(obj: T): ToRefs<T> {
-  if (__DEV__ && !isReactive(obj) && !isPropObject(obj)) {
+  if (__DEV__ && !isReactive(obj)) {
     warn(`toRefs() expects a reactive object but received a plain one.`)
   }
   if (!isPlainObject(obj)) return obj as any
diff --git a/src/utils/symbols.ts b/src/utils/symbols.ts
index 584a0ee..00e5985 100644
--- a/src/utils/symbols.ts
+++ b/src/utils/symbols.ts
@@ -13,4 +13,3 @@ export const WatcherPostFlushQueueKey = createSymbol(
 
 // must be a string, symbol key is ignored in reactive
 export const RefKey = 'composition-api.refKey'
-export const PropsReactive = '__props_reactive__'


Test patch:
diff --git a/test/setup.spec.js b/test/setup.spec.js
index 1e2b6a1..b3bd34e 100644
--- a/test/setup.spec.js
+++ b/test/setup.spec.js
@@ -10,8 +10,9 @@ const {
   markRaw,
   toRaw,
   nextTick,
+  isReactive,
   defineComponent,
-  onMounted,
+  onMounted
 } = require('../src')
 const { sleep } = require('./helpers/utils')
 
@@ -58,7 +59,7 @@ describe('setup', () => {
     expect(vm.b).toBe('foobar')
   })
 
-  it('should be overrided by data option of plain object', () => {
+  it('should be overridden by data option of plain object', () => {
     const vm = new Vue({
       setup() {
         return {
@@ -303,8 +304,9 @@ describe('setup', () => {
     expect(vm.$refs.test.b).toBe(1)
   })
 
-  it('props should not be reactive', (done) => {
+  it('props should be reactive', (done) => {
     let calls = 0
+    let _props
     const vm = new Vue({
       template: `<child :msg="msg"></child>`,
       setup() {
@@ -318,6 +320,8 @@ describe('setup', () => {
           template: `<span>{{ localMsg }}</span>`,
           props: ['msg'],
           setup(props) {
+            _props = props
+
             return {
               localMsg: props.msg,
               computedMsg: computed(() => props.msg + ' world'),
@@ -326,6 +330,9 @@ describe('setup', () => {
         },
       },
     }).$mount()
+
+    expect(isReactive(_props)).toBe(true)
+
     const child = vm.$children[0]
     expect(child.localMsg).toBe('hello')
     expect(child.computedMsg).toBe('hello world')