fix(runtime-core): ensure declare prop keys are always present
fix #3288
This commit is contained in:
parent
f0cf14bcc5
commit
4fe4de0a49
@ -11,7 +11,8 @@ import {
|
|||||||
createApp,
|
createApp,
|
||||||
provide,
|
provide,
|
||||||
inject,
|
inject,
|
||||||
watch
|
watch,
|
||||||
|
toRefs
|
||||||
} from '@vue/runtime-test'
|
} from '@vue/runtime-test'
|
||||||
import { render as domRender, nextTick } from 'vue'
|
import { render as domRender, nextTick } from 'vue'
|
||||||
|
|
||||||
@ -479,4 +480,32 @@ describe('component props', () => {
|
|||||||
expect(serializeInner(root)).toMatch(`<h1>11</h1>`)
|
expect(serializeInner(root)).toMatch(`<h1>11</h1>`)
|
||||||
expect(count).toBe(0)
|
expect(count).toBe(0)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// #3288
|
||||||
|
test('declared prop key should be present even if not passed', async () => {
|
||||||
|
let initialKeys: string[] = []
|
||||||
|
const changeSpy = jest.fn()
|
||||||
|
const passFoo = ref(false)
|
||||||
|
|
||||||
|
const Comp = {
|
||||||
|
render() {},
|
||||||
|
props: {
|
||||||
|
foo: String
|
||||||
|
},
|
||||||
|
setup(props: any) {
|
||||||
|
initialKeys = Object.keys(props)
|
||||||
|
const { foo } = toRefs(props)
|
||||||
|
watch(foo, changeSpy)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Parent = () => (passFoo.value ? h(Comp, { foo: 'ok' }) : h(Comp))
|
||||||
|
const root = nodeOps.createElement('div')
|
||||||
|
createApp(Parent).mount(root)
|
||||||
|
|
||||||
|
expect(initialKeys).toMatchObject(['foo'])
|
||||||
|
passFoo.value = true
|
||||||
|
await nextTick()
|
||||||
|
expect(changeSpy).toHaveBeenCalledTimes(1)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -143,6 +143,14 @@ export function initProps(
|
|||||||
instance.propsDefaults = Object.create(null)
|
instance.propsDefaults = Object.create(null)
|
||||||
|
|
||||||
setFullProps(instance, rawProps, props, attrs)
|
setFullProps(instance, rawProps, props, attrs)
|
||||||
|
|
||||||
|
// ensure all declared prop keys are present
|
||||||
|
for (const key in instance.propsOptions[0]) {
|
||||||
|
if (!(key in props)) {
|
||||||
|
props[key] = undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// validation
|
// validation
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
validateProps(rawProps || {}, props, instance)
|
validateProps(rawProps || {}, props, instance)
|
||||||
@ -281,11 +289,11 @@ function setFullProps(
|
|||||||
const [options, needCastKeys] = instance.propsOptions
|
const [options, needCastKeys] = instance.propsOptions
|
||||||
if (rawProps) {
|
if (rawProps) {
|
||||||
for (const key in rawProps) {
|
for (const key in rawProps) {
|
||||||
const value = rawProps[key]
|
|
||||||
// key, ref are reserved and never passed down
|
// key, ref are reserved and never passed down
|
||||||
if (isReservedProp(key)) {
|
if (isReservedProp(key)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
const value = rawProps[key]
|
||||||
// prop option names are camelized during normalization, so to support
|
// prop option names are camelized during normalization, so to support
|
||||||
// kebab -> camel conversion here we need to camelize the key.
|
// kebab -> camel conversion here we need to camelize the key.
|
||||||
let camelKey
|
let camelKey
|
||||||
|
Loading…
x
Reference in New Issue
Block a user