diff --git a/src/core/instance/state.ts b/src/core/instance/state.ts index aedb72555..7ac84c6ba 100644 --- a/src/core/instance/state.ts +++ b/src/core/instance/state.ts @@ -95,19 +95,25 @@ function initProps(vm: Component, propsOptions: Object) { vm ) } - defineReactive(props, key, value, () => { - if (!isRoot && !isUpdatingChildComponent) { - warn( - `Avoid mutating a prop directly since the value will be ` + - `overwritten whenever the parent component re-renders. ` + - `Instead, use a data or computed property based on the prop's ` + - `value. Prop being mutated: "${key}"`, - vm - ) - } - }) + defineReactive( + props, + key, + value, + () => { + if (!isRoot && !isUpdatingChildComponent) { + warn( + `Avoid mutating a prop directly since the value will be ` + + `overwritten whenever the parent component re-renders. ` + + `Instead, use a data or computed property based on the prop's ` + + `value. Prop being mutated: "${key}"`, + vm + ) + } + }, + true + ) } else { - defineReactive(props, key, value) + defineReactive(props, key, value, undefined, true) } // static props are already proxied on the component's prototype // during Vue.extend(). We only need to proxy props defined at diff --git a/test/unit/features/options/props.spec.ts b/test/unit/features/options/props.spec.ts index d1d2a6b00..23f30df42 100644 --- a/test/unit/features/options/props.spec.ts +++ b/test/unit/features/options/props.spec.ts @@ -1,6 +1,7 @@ import Vue from 'vue' import { hasSymbol } from 'core/util/env' import testObjectOption from '../../../helpers/test-object-option' +import { ref } from 'v3' describe('Options props', () => { testObjectOption('props') @@ -593,4 +594,21 @@ describe('Options props', () => { 'Invalid prop type: "String" is not a constructor' ).toHaveBeenWarned() }) + + // #12930 + it('should not unwrap prop values that are raw refs', () => { + let val + const Comp = { + props: ['msg'], + created() { + val = this.msg + }, + render() {} + } + const r = ref() + new Vue({ + render: h => h(Comp, { props: { msg: r }}) + }).$mount() + expect(val).toBe(r) + }) })