diff --git a/src/core/util/props.ts b/src/core/util/props.ts index 795f5ac37a6..0773ecff734 100644 --- a/src/core/util/props.ts +++ b/src/core/util/props.ts @@ -1,5 +1,6 @@ import { warn } from './debug' import { observe, toggleObserving, shouldObserve } from '../observer/index' +import { isRef } from '../../v3' import { hasOwn, isArray, @@ -109,6 +110,7 @@ function assertProp( vm?: Component, absent?: boolean ) { + value = isRef(value) ? value.value : value if (prop.required && absent) { warn('Missing required prop: "' + name + '"', vm) return diff --git a/test/unit/features/options/props.spec.ts b/test/unit/features/options/props.spec.ts index d1d2a6b00f5..10e93214ab2 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, h } from 'v3' describe('Options props', () => { testObjectOption('props') @@ -593,4 +594,36 @@ describe('Options props', () => { 'Invalid prop type: "String" is not a constructor' ).toHaveBeenWarned() }) + + // #12930 + it('should work with ref unwrap', function () { + function makeInstance(value, type) { + const Comp = { + props: { + msg: { + type + } + }, + setup() { + return () => h('div') + } + } + const App = { + setup() { + const msg = ref(value) + return () => h(Comp, { props: { msg } }) + } + } + return new Vue(App).$mount() + } + + makeInstance('123', String) + expect((console.error as any).mock.calls.length).toBe(0) + makeInstance('123', Object) + expect('Expected Object, got String with value "123"').toHaveBeenWarned() + makeInstance('123', Number) + expect( + 'Expected Number with value 123, got String with value "123"' + ).toHaveBeenWarned() + }) })