diff --git a/packages/compiler-sfc/__tests__/compileScript/__snapshots__/definePropsDestructure.spec.ts.snap b/packages/compiler-sfc/__tests__/compileScript/__snapshots__/definePropsDestructure.spec.ts.snap
index 1044b0e167c..2957a42292a 100644
--- a/packages/compiler-sfc/__tests__/compileScript/__snapshots__/definePropsDestructure.spec.ts.snap
+++ b/packages/compiler-sfc/__tests__/compileScript/__snapshots__/definePropsDestructure.spec.ts.snap
@@ -101,13 +101,14 @@ exports[`sfc reactive props destructure > default values w/ runtime declaration
"import { mergeDefaults as _mergeDefaults } from 'vue'
export default {
- props: /*@__PURE__*/_mergeDefaults(['foo', 'foo:bar'], {
+ props: /*@__PURE__*/_mergeDefaults(['foo', 'foo:bar', 'baz'], {
foo: 1,
- "foo:bar": 'foo-bar'
+ "foo:bar": 'foo-bar',
+ baz: (props) => (props["foo"])
}),
setup(__props) {
-
+ __props.foo
return () => {}
}
@@ -142,11 +143,12 @@ export default /*@__PURE__*/_defineComponent({
props: {
foo: { type: Number, required: false, default: 1 },
bar: { type: Object, required: false, default: () => ({}) },
- func: { type: Function, required: false, default: () => {} }
+ func: { type: Function, required: false, default: () => {} },
+ baz: { type: Object, required: false, default: (props) => (props["bar"]) }
},
setup(__props: any) {
-
+ __props.bar
return () => {}
}
diff --git a/packages/compiler-sfc/__tests__/compileScript/definePropsDestructure.spec.ts b/packages/compiler-sfc/__tests__/compileScript/definePropsDestructure.spec.ts
index 50602eb59bc..de242e91452 100644
--- a/packages/compiler-sfc/__tests__/compileScript/definePropsDestructure.spec.ts
+++ b/packages/compiler-sfc/__tests__/compileScript/definePropsDestructure.spec.ts
@@ -106,25 +106,28 @@ describe('sfc reactive props destructure', () => {
})`)
assertCode(content)
})
+
test('default values w/ runtime declaration & key is string', () => {
const { content, bindings } = compile(`
`)
expect(bindings).toStrictEqual({
__propsAliases: {
fooBar: 'foo:bar',
},
+ baz: BindingTypes.PROPS,
foo: BindingTypes.PROPS,
'foo:bar': BindingTypes.PROPS,
fooBar: BindingTypes.PROPS_ALIASED,
})
expect(content).toMatch(`
- props: /*@__PURE__*/_mergeDefaults(['foo', 'foo:bar'], {
+ props: /*@__PURE__*/_mergeDefaults(['foo', 'foo:bar', 'baz'], {
foo: 1,
- "foo:bar": 'foo-bar'
+ "foo:bar": 'foo-bar',
+ baz: (props) => (props["foo"])
}),`)
assertCode(content)
})
@@ -132,7 +135,7 @@ describe('sfc reactive props destructure', () => {
test('default values w/ type declaration', () => {
const { content } = compile(`
`)
// literals can be used as-is, non-literals are always returned from a
@@ -140,7 +143,8 @@ describe('sfc reactive props destructure', () => {
expect(content).toMatch(`props: {
foo: { type: Number, required: false, default: 1 },
bar: { type: Object, required: false, default: () => ({}) },
- func: { type: Function, required: false, default: () => {} }
+ func: { type: Function, required: false, default: () => {} },
+ baz: { type: Object, required: false, default: (props) => (props["bar"]) }
}`)
assertCode(content)
})
diff --git a/packages/compiler-sfc/src/script/defineProps.ts b/packages/compiler-sfc/src/script/defineProps.ts
index 9a4880a1a54..a89c89769b7 100644
--- a/packages/compiler-sfc/src/script/defineProps.ts
+++ b/packages/compiler-sfc/src/script/defineProps.ts
@@ -349,13 +349,16 @@ function genDestructuredDefaultValue(
}
}
+ const isDestructuredBinding = ctx.propsDestructuredBindings[value]
+
// If the default value is a function or is an identifier referencing
// external value, skip factory wrap. This is needed when using
// destructure w/ runtime declaration since we cannot safely infer
// whether the expected runtime prop type is `Function`.
const needSkipFactory =
!inferredType &&
- (isFunctionType(unwrapped) || unwrapped.type === 'Identifier')
+ (isFunctionType(unwrapped) ||
+ (unwrapped.type === 'Identifier' && !isDestructuredBinding))
const needFactoryWrap =
!needSkipFactory &&
@@ -363,13 +366,17 @@ function genDestructuredDefaultValue(
!inferredType?.includes('Function')
return {
- valueString: needFactoryWrap ? `() => (${value})` : value,
+ valueString: needFactoryWrap
+ ? isDestructuredBinding
+ ? `(props) => (props["${value}"])`
+ : `() => (${value})`
+ : value,
needSkipFactory,
}
}
}
-// non-comprehensive, best-effort type infernece for a runtime value
+// non-comprehensive, best-effort type inference for a runtime value
// this is used to catch default value / type declaration mismatches
// when using props destructure.
function inferValueType(node: Node): string | undefined {