foo: { type: String, required: false, default: 'hi' },
bar: { type: Number, required: false },
baz: { type: Boolean, required: true },
- qux: { type: Function, required: false, default() { return 1 } }
+ qux: { type: Function, required: false, default() { return 1 } },
+ quux: { type: Function, required: false, default() { } }
},
setup(__props: any, { expose }) {
expose();
-const props = __props as { foo: string, bar?: number, baz: boolean, qux(): number };
+const props = __props as { foo: string, bar?: number, baz: boolean, qux(): number, quux(): void };
foo?: string
bar?: number;
baz: boolean;
- qux?(): number
+ qux?(): number;
+ quux?(): void
}>(), {
foo: 'hi',
- qux() { return 1 }
+ qux() { return 1 },
+ ['quux']() { }
})
</script>
`)
`qux: { type: Function, required: false, default() { return 1 } }`
)
expect(content).toMatch(
- `{ foo: string, bar?: number, baz: boolean, qux(): number }`
+ `quux: { type: Function, required: false, default() { } }`
+ )
+ expect(content).toMatch(
+ `{ foo: string, bar?: number, baz: boolean, qux(): number, quux(): void }`
)
expect(content).toMatch(`const props = __props`)
expect(bindings).toStrictEqual({
bar: BindingTypes.PROPS,
baz: BindingTypes.PROPS,
qux: BindingTypes.PROPS,
+ quux: BindingTypes.PROPS,
props: BindingTypes.SETUP_CONST
})
})
assertCode(content)
})
+ // #6960
+ test('computed static key', () => {
+ const { content, bindings } = compile(`
+ <script setup>
+ const { ['foo']: foo } = defineProps(['foo'])
+ console.log(foo)
+ </script>
+ <template>{{ foo }}</template>
+ `)
+ expect(content).not.toMatch(`const { foo } =`)
+ expect(content).toMatch(`console.log(__props.foo)`)
+ expect(content).toMatch(`_toDisplayString(__props.foo)`)
+ assertCode(content)
+ expect(bindings).toStrictEqual({
+ foo: BindingTypes.PROPS
+ })
+ })
+
describe('errors', () => {
test('should error on deep destructure', () => {
expect(() =>
// props destructure - handle compilation sugar
for (const prop of declId.properties) {
if (prop.type === 'ObjectProperty') {
- if (prop.computed) {
+ const propKey = resolveObjectKey(prop.key, prop.computed)
+
+ if (!propKey) {
error(
`${DEFINE_PROPS}() destructure cannot use computed key.`,
prop.key
)
}
- const propKey =
- prop.key.type === 'StringLiteral'
- ? prop.key.value
- : (prop.key as Identifier).name
-
if (prop.value.type === 'AssignmentPattern') {
// default value { foo = 123 }
const { left, right } = prop.value
propsRuntimeDefaults.type === 'ObjectExpression' &&
propsRuntimeDefaults.properties.every(
node =>
- (node.type === 'ObjectProperty' && !node.computed) ||
+ (node.type === 'ObjectProperty' &&
+ (!node.computed || node.key.type.endsWith('Literal'))) ||
node.type === 'ObjectMethod'
)
)
if (destructured) {
defaultString = `default: ${destructured}`
} else if (hasStaticDefaults) {
- const prop = propsRuntimeDefaults!.properties.find(
- (node: any) => node.key.name === key
- ) as ObjectProperty | ObjectMethod
+ const prop = propsRuntimeDefaults!.properties.find(node => {
+ if (node.type === 'SpreadElement') return false
+ return resolveObjectKey(node.key, node.computed) === key
+ }) as ObjectProperty | ObjectMethod
if (prop) {
if (prop.type === 'ObjectProperty') {
// prop has corresponding static default value
m.key.type === 'Identifier'
) {
if (
- propsRuntimeDefaults!.properties.some(
- (p: any) => p.key.name === (m.key as Identifier).name
- )
+ propsRuntimeDefaults!.properties.some(p => {
+ if (p.type === 'SpreadElement') return false
+ return (
+ resolveObjectKey(p.key, p.computed) ===
+ (m.key as Identifier).name
+ )
+ })
) {
res +=
m.key.name +
function getObjectExpressionKeys(node: ObjectExpression): string[] {
const keys = []
for (const prop of node.properties) {
- if (
- (prop.type === 'ObjectProperty' || prop.type === 'ObjectMethod') &&
- !prop.computed
- ) {
- if (prop.key.type === 'Identifier') {
- keys.push(prop.key.name)
- } else if (prop.key.type === 'StringLiteral') {
- keys.push(prop.key.value)
- }
- }
+ if (prop.type === 'SpreadElement') continue
+ const key = resolveObjectKey(prop.key, prop.computed)
+ if (key) keys.push(String(key))
}
return keys
}
return false
}
+
+export function resolveObjectKey(node: Node, computed: boolean) {
+ switch (node.type) {
+ case 'StringLiteral':
+ case 'NumericLiteral':
+ return node.value
+ case 'Identifier':
+ if (!computed) return node.name
+ }
+ return undefined
+}