diff --git a/packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap b/packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap
index ec94872c560..55659cb93d3 100644
--- a/packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap
+++ b/packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap
@@ -1743,12 +1743,13 @@ export default /*#__PURE__*/_defineComponent({
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 };
diff --git a/packages/compiler-sfc/__tests__/__snapshots__/compileScriptPropsTransform.spec.ts.snap b/packages/compiler-sfc/__tests__/__snapshots__/compileScriptPropsTransform.spec.ts.snap
index 093d2b9ddf7..cbbdaabd9b5 100644
--- a/packages/compiler-sfc/__tests__/__snapshots__/compileScriptPropsTransform.spec.ts.snap
+++ b/packages/compiler-sfc/__tests__/__snapshots__/compileScriptPropsTransform.spec.ts.snap
@@ -59,6 +59,25 @@ return (_ctx, _cache) => {
}"
`;
+exports[`sfc props transform computed static key 1`] = `
+"import { toDisplayString as _toDisplayString } from \\"vue\\"
+
+
+export default {
+ props: ['foo'],
+ setup(__props) {
+
+
+ console.log(__props.foo)
+
+return (_ctx, _cache) => {
+ return _toDisplayString(__props.foo)
+}
+}
+
+}"
+`;
+
exports[`sfc props transform default values w/ runtime declaration 1`] = `
"import { mergeDefaults as _mergeDefaults } from 'vue'
diff --git a/packages/compiler-sfc/__tests__/compileScript.spec.ts b/packages/compiler-sfc/__tests__/compileScript.spec.ts
index 4e3e36f7431..c3ba6067648 100644
--- a/packages/compiler-sfc/__tests__/compileScript.spec.ts
+++ b/packages/compiler-sfc/__tests__/compileScript.spec.ts
@@ -1039,10 +1039,12 @@ const emit = defineEmits(['a', 'b'])
foo?: string
bar?: number;
baz: boolean;
- qux?(): number
+ qux?(): number;
+ quux?(): void
}>(), {
foo: 'hi',
- qux() { return 1 }
+ qux() { return 1 },
+ ['quux']() { }
})
`)
@@ -1056,7 +1058,10 @@ const emit = defineEmits(['a', 'b'])
`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({
@@ -1064,6 +1069,7 @@ const emit = defineEmits(['a', 'b'])
bar: BindingTypes.PROPS,
baz: BindingTypes.PROPS,
qux: BindingTypes.PROPS,
+ quux: BindingTypes.PROPS,
props: BindingTypes.SETUP_CONST
})
})
diff --git a/packages/compiler-sfc/__tests__/compileScriptPropsTransform.spec.ts b/packages/compiler-sfc/__tests__/compileScriptPropsTransform.spec.ts
index 25fb4bed280..7d35f91abf2 100644
--- a/packages/compiler-sfc/__tests__/compileScriptPropsTransform.spec.ts
+++ b/packages/compiler-sfc/__tests__/compileScriptPropsTransform.spec.ts
@@ -184,6 +184,24 @@ describe('sfc props transform', () => {
assertCode(content)
})
+ // #6960
+ test('computed static key', () => {
+ const { content, bindings } = compile(`
+
+ {{ foo }}
+ `)
+ 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(() =>
diff --git a/packages/compiler-sfc/src/compileScript.ts b/packages/compiler-sfc/src/compileScript.ts
index aba5a22ec8d..d55cb795c77 100644
--- a/packages/compiler-sfc/src/compileScript.ts
+++ b/packages/compiler-sfc/src/compileScript.ts
@@ -447,18 +447,15 @@ export function compileScript(
// 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
@@ -774,7 +771,8 @@ export function compileScript(
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'
)
)
@@ -795,9 +793,10 @@ export function compileScript(
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
@@ -874,9 +873,13 @@ export function compileScript(
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 +
@@ -2139,16 +2142,9 @@ function analyzeBindingsFromOptions(node: ObjectExpression): BindingMetadata {
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
}
@@ -2297,3 +2293,14 @@ export function hmrShouldReload(
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
+}