diff --git a/packages/compiler-core/src/transforms/transformExpression.ts b/packages/compiler-core/src/transforms/transformExpression.ts
index a3a48be6..e4311ad4 100644
--- a/packages/compiler-core/src/transforms/transformExpression.ts
+++ b/packages/compiler-core/src/transforms/transformExpression.ts
@@ -24,7 +24,13 @@ import {
walkIdentifiers
} from '../babelUtils'
import { advancePositionWithClone, isSimpleIdentifier } from '../utils'
-import { isGloballyWhitelisted, makeMap, hasOwn, isString } from '@vue/shared'
+import {
+ isGloballyWhitelisted,
+ makeMap,
+ hasOwn,
+ isString,
+ genPropsAccessExp
+} from '@vue/shared'
import { createCompilerError, ErrorCodes } from '../errors'
import {
Node,
@@ -185,17 +191,17 @@ export function processExpression(
} else if (type === BindingTypes.PROPS) {
// use __props which is generated by compileScript so in ts mode
// it gets correct type
- return `__props.${raw}`
+ return genPropsAccessExp(raw)
} else if (type === BindingTypes.PROPS_ALIASED) {
// prop with a different local alias (from defineProps() destructure)
- return `__props.${bindingMetadata.__propsAliases![raw]}`
+ return genPropsAccessExp(bindingMetadata.__propsAliases![raw])
}
} else {
if (type && type.startsWith('setup')) {
// setup bindings in non-inline mode
return `$setup.${raw}`
} else if (type === BindingTypes.PROPS_ALIASED) {
- return `$props.${bindingMetadata.__propsAliases![raw]}`
+ return `$props['${bindingMetadata.__propsAliases![raw]}']`
} else if (type) {
return `$${type}.${raw}`
}
diff --git a/packages/compiler-sfc/__tests__/__snapshots__/compileScriptPropsTransform.spec.ts.snap b/packages/compiler-sfc/__tests__/__snapshots__/compileScriptPropsTransform.spec.ts.snap
index 8a735942..cfde6700 100644
--- a/packages/compiler-sfc/__tests__/__snapshots__/compileScriptPropsTransform.spec.ts.snap
+++ b/packages/compiler-sfc/__tests__/__snapshots__/compileScriptPropsTransform.spec.ts.snap
@@ -134,6 +134,25 @@ return () => {}
}"
`;
+exports[`sfc props transform non-identifier prop names 1`] = `
+"import { toDisplayString as _toDisplayString } from \\"vue\\"
+
+
+export default {
+ props: { 'foo.bar': Function },
+ setup(__props) {
+
+
+ let x = __props[\\"foo.bar\\"]
+
+return (_ctx, _cache) => {
+ return _toDisplayString(__props[\\"foo.bar\\"])
+}
+}
+
+}"
+`;
+
exports[`sfc props transform rest spread 1`] = `
"import { createPropsRestProxy as _createPropsRestProxy } from 'vue'
diff --git a/packages/compiler-sfc/__tests__/compileScriptPropsTransform.spec.ts b/packages/compiler-sfc/__tests__/compileScriptPropsTransform.spec.ts
index 0dafc020..25fb4bed 100644
--- a/packages/compiler-sfc/__tests__/compileScriptPropsTransform.spec.ts
+++ b/packages/compiler-sfc/__tests__/compileScriptPropsTransform.spec.ts
@@ -127,6 +127,28 @@ describe('sfc props transform', () => {
})
})
+ // #5425
+ test('non-identifier prop names', () => {
+ const { content, bindings } = compile(`
+
+ {{ fooBar }}
+ `)
+ expect(content).toMatch(`x = __props["foo.bar"]`)
+ expect(content).toMatch(`toDisplayString(__props["foo.bar"])`)
+ assertCode(content)
+ expect(bindings).toStrictEqual({
+ x: BindingTypes.SETUP_LET,
+ 'foo.bar': BindingTypes.PROPS,
+ fooBar: BindingTypes.PROPS_ALIASED,
+ __propsAliases: {
+ fooBar: 'foo.bar'
+ }
+ })
+ })
+
test('rest spread', () => {
const { content, bindings } = compile(`