From 242914d938fccad1c09a52a7ed09f15ac509cf6b Mon Sep 17 00:00:00 2001 From: edison Date: Fri, 13 May 2022 10:38:46 +0800 Subject: [PATCH] fix(reactivity-transform): fix props access codegen for non-identifier prop names (#5436) fix #5425 --- .../src/transforms/transformExpression.ts | 14 ++++++++---- .../compileScriptPropsTransform.spec.ts.snap | 19 ++++++++++++++++ .../compileScriptPropsTransform.spec.ts | 22 +++++++++++++++++++ packages/compiler-sfc/src/compileScript.ts | 6 ++++- .../src/reactivityTransform.ts | 10 ++++----- packages/shared/src/index.ts | 8 +++++++ 6 files changed, 69 insertions(+), 10 deletions(-) diff --git a/packages/compiler-core/src/transforms/transformExpression.ts b/packages/compiler-core/src/transforms/transformExpression.ts index a3a48be61..e4311ad4f 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 8a7359420..cfde6700d 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 0dafc0200..25fb4bed2 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(` + + + `) + 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(`