From 52cf912d855a7fae8d8c89452f0d275846e26a87 Mon Sep 17 00:00:00 2001 From: Evan You Date: Mon, 20 Jun 2022 13:09:56 +0800 Subject: [PATCH] fix(setup): setup props should pass isReactive check close #12561 --- src/core/instance/state.ts | 4 ++-- src/v3/apiSetup.ts | 6 +++++- test/unit/features/v3/apiSetup.spec.ts | 22 +++++++++++++++++++++- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/core/instance/state.ts b/src/core/instance/state.ts index 4262e0647..e22ec6705 100644 --- a/src/core/instance/state.ts +++ b/src/core/instance/state.ts @@ -30,7 +30,7 @@ import { isFunction } from '../util/index' import type { Component } from 'types/component' -import { TrackOpTypes } from '../../v3' +import { shallowReactive, TrackOpTypes } from 'v3' const sharedPropertyDefinition = { enumerable: true, @@ -71,7 +71,7 @@ export function initState(vm: Component) { function initProps(vm: Component, propsOptions: Object) { const propsData = vm.$options.propsData || {} - const props = (vm._props = {}) + const props = (vm._props = shallowReactive({})) // cache prop keys so that future props updates can iterate using Array // instead of dynamic object key enumeration. const keys: string[] = (vm.$options._propKeys = []) diff --git a/src/v3/apiSetup.ts b/src/v3/apiSetup.ts index 811453b99..dcb263cb7 100644 --- a/src/v3/apiSetup.ts +++ b/src/v3/apiSetup.ts @@ -1,5 +1,6 @@ import { Component } from 'types/component' import { PropOptions } from 'types/options' +import { toggleObserving } from '../core/observer' import { def, invokeWithErrorHandling, isReserved, warn } from '../core/util' import VNode from '../core/vdom/vnode' import { @@ -10,6 +11,7 @@ import { isObject } from '../shared/util' import { currentInstance, setCurrentInstance } from './currentInstance' +import { shallowReactive } from './reactivity/reactive' import { isRef } from './reactivity/ref' /** @@ -29,13 +31,15 @@ export function initSetup(vm: Component) { const ctx = (vm._setupContext = createSetupContext(vm)) setCurrentInstance(vm) + toggleObserving(false) const setupResult = invokeWithErrorHandling( setup, null, - [vm._props, ctx], + [vm._props || shallowReactive({}), ctx], vm, `setup` ) + toggleObserving(true) setCurrentInstance() if (isFunction(setupResult)) { diff --git a/test/unit/features/v3/apiSetup.spec.ts b/test/unit/features/v3/apiSetup.spec.ts index 44044ed22..629e48857 100644 --- a/test/unit/features/v3/apiSetup.spec.ts +++ b/test/unit/features/v3/apiSetup.spec.ts @@ -1,4 +1,4 @@ -import { h, ref, reactive } from 'v3' +import { h, ref, reactive, isReactive, toRef, isRef } from 'v3' import { nextTick } from 'core/util' import { effect } from 'v3/reactivity/effect' import Vue from 'vue' @@ -247,4 +247,24 @@ describe('api: setup context', () => { }).$mount() expect(spy).toHaveBeenCalled() }) + + // #12561 + it.only('setup props should be reactive', () => { + const msg = ref('hi') + + const Child = { + props: ['msg'], + setup: props => { + expect(isReactive(props)).toBe(true) + expect(isRef(toRef(props, 'foo'))).toBe(true) + return () => {} + } + } + + new Vue({ + setup() { + return h => h(Child, { props: { msg } }) + } + }).$mount() + }) })