fix(reactivity-transform): fix props access codegen for non-identifier prop names (#5436)
fix #5425
This commit is contained in:
parent
0c07f12541
commit
242914d938
@ -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}`
|
||||
}
|
||||
|
@ -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'
|
||||
|
||||
|
@ -127,6 +127,28 @@ describe('sfc props transform', () => {
|
||||
})
|
||||
})
|
||||
|
||||
// #5425
|
||||
test('non-identifier prop names', () => {
|
||||
const { content, bindings } = compile(`
|
||||
<script setup>
|
||||
const { 'foo.bar': fooBar } = defineProps({ 'foo.bar': Function })
|
||||
let x = fooBar
|
||||
</script>
|
||||
<template>{{ fooBar }}</template>
|
||||
`)
|
||||
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(`
|
||||
<script setup>
|
||||
|
@ -431,7 +431,11 @@ export function compileScript(
|
||||
prop.key
|
||||
)
|
||||
}
|
||||
const propKey = (prop.key as Identifier).name
|
||||
|
||||
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
|
||||
|
@ -21,7 +21,7 @@ import {
|
||||
walkFunctionParams
|
||||
} from '@vue/compiler-core'
|
||||
import { parse, ParserPlugin } from '@babel/parser'
|
||||
import { hasOwn, isArray, isString } from '@vue/shared'
|
||||
import { hasOwn, isArray, isString, genPropsAccessExp } from '@vue/shared'
|
||||
|
||||
const CONVERT_SYMBOL = '$'
|
||||
const ESCAPE_SYMBOL = '$$'
|
||||
@ -489,17 +489,17 @@ export function transformAST(
|
||||
if (isProp) {
|
||||
if (escapeScope) {
|
||||
// prop binding in $$()
|
||||
// { prop } -> { prop: __prop_prop }
|
||||
// { prop } -> { prop: __props_prop }
|
||||
registerEscapedPropBinding(id)
|
||||
s.appendLeft(
|
||||
id.end! + offset,
|
||||
`: __props_${propsLocalToPublicMap[id.name]}`
|
||||
)
|
||||
} else {
|
||||
// { prop } -> { prop: __prop.prop }
|
||||
// { prop } -> { prop: __props.prop }
|
||||
s.appendLeft(
|
||||
id.end! + offset,
|
||||
`: __props.${propsLocalToPublicMap[id.name]}`
|
||||
`: ${genPropsAccessExp(propsLocalToPublicMap[id.name])}`
|
||||
)
|
||||
}
|
||||
} else {
|
||||
@ -522,7 +522,7 @@ export function transformAST(
|
||||
s.overwrite(
|
||||
id.start! + offset,
|
||||
id.end! + offset,
|
||||
`__props.${propsLocalToPublicMap[id.name]}`
|
||||
genPropsAccessExp(propsLocalToPublicMap[id.name])
|
||||
)
|
||||
}
|
||||
} else {
|
||||
|
@ -171,3 +171,11 @@ export const getGlobalThis = (): any => {
|
||||
: {})
|
||||
)
|
||||
}
|
||||
|
||||
const identRE = /^[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*$/
|
||||
|
||||
export function genPropsAccessExp(name: string) {
|
||||
return identRE.test(name)
|
||||
? `__props.${name}`
|
||||
: `__props[${JSON.stringify(name)}]`
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user