]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(compiler-sfc): resolve computed object key (#6963)
author三咲智子 Kevin Deng <sxzz@sxzz.moe>
Wed, 9 Nov 2022 02:57:40 +0000 (10:57 +0800)
committerGitHub <noreply@github.com>
Wed, 9 Nov 2022 02:57:40 +0000 (21:57 -0500)
packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap
packages/compiler-sfc/__tests__/__snapshots__/compileScriptPropsTransform.spec.ts.snap
packages/compiler-sfc/__tests__/compileScript.spec.ts
packages/compiler-sfc/__tests__/compileScriptPropsTransform.spec.ts
packages/compiler-sfc/src/compileScript.ts

index ec94872c5607818304d66175fc749711178dacc7..55659cb93d3bb270a7952d970e0714cb5c9861a4 100644 (file)
@@ -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 };
 
       
       
index 093d2b9ddf7ce36958e48d528e9641637b1ada86..cbbdaabd9b5c26906b7cc01f74f5a2e6cc5616e9 100644 (file)
@@ -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'
 
index 4e3e36f743103482ce7b587ccfb224d41c639a78..c3ba6067648fac86100b2e6103289318ac808a1a 100644 (file)
@@ -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']() { }
       })
       </script>
       `)
@@ -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
       })
     })
index 25fb4bed2800cf64076b5731229be9cb2b6d75fb..7d35f91abf273e1e0975d347dbaad9a8a30586c2 100644 (file)
@@ -184,6 +184,24 @@ describe('sfc props transform', () => {
     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(() =>
index aba5a22ec8d673a10a043815fefe5c0b4ed4b57d..d55cb795c771140ebc448b61497e48f1acd2ef8c 100644 (file)
@@ -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
+}