Просмотр исходного кода

feat(compiler-sfc): support arbitrary expression as withDefaults argument

ref #6459
Evan You 3 лет назад
Родитель
Сommit
fe619443d2

+ 27 - 0
packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap

@@ -1901,6 +1901,33 @@ const props = __props as {
 
 
       
       
       
       
+return { props, get defaults() { return defaults } }
+}
+
+})"
+`;
+
+exports[`SFC compile <script setup> > with TypeScript > withDefaults (reference) 1`] = `
+"import { mergeDefaults as _mergeDefaults, defineComponent as _defineComponent } from 'vue'
+import { defaults } from './foo'
+      
+export default /*#__PURE__*/_defineComponent({
+  props: _mergeDefaults({
+    foo: { type: String, required: false },
+    bar: { type: Number, required: false },
+    baz: { type: Boolean, required: true }
+  }, defaults),
+  setup(__props: any, { expose: __expose }) {
+  __expose();
+
+const props = __props as {
+        foo?: string
+        bar?: number
+        baz: boolean
+      };
+
+      
+      
 return { props, get defaults() { return defaults } }
 return { props, get defaults() { return defaults } }
 }
 }
 
 

+ 23 - 0
packages/compiler-sfc/__tests__/compileScript.spec.ts

@@ -1378,6 +1378,29 @@ const emit = defineEmits(['a', 'b'])
       )
       )
     })
     })
 
 
+    test('withDefaults (reference)', () => {
+      const { content } = compile(`
+      <script setup lang="ts">
+      import { defaults } from './foo'
+      const props = withDefaults(defineProps<{
+        foo?: string
+        bar?: number
+        baz: boolean
+      }>(), defaults)
+      </script>
+      `)
+      assertCode(content)
+      expect(content).toMatch(`import { mergeDefaults as _mergeDefaults`)
+      expect(content).toMatch(
+        `
+  _mergeDefaults({
+    foo: { type: String, required: false },
+    bar: { type: Number, required: false },
+    baz: { type: Boolean, required: true }
+  }, defaults)`.trim()
+      )
+    })
+
     // #7111
     // #7111
     test('withDefaults (dynamic) w/ production mode', () => {
     test('withDefaults (dynamic) w/ production mode', () => {
       const { content } = compile(
       const { content } = compile(

+ 8 - 12
packages/compiler-sfc/src/compileScript.ts

@@ -313,7 +313,7 @@ export function compileScript(
   let hasDefaultExportRender = false
   let hasDefaultExportRender = false
   let hasDefineOptionsCall = false
   let hasDefineOptionsCall = false
   let propsRuntimeDecl: Node | undefined
   let propsRuntimeDecl: Node | undefined
-  let propsRuntimeDefaults: ObjectExpression | undefined
+  let propsRuntimeDefaults: Node | undefined
   let propsDestructureDecl: Node | undefined
   let propsDestructureDecl: Node | undefined
   let propsDestructureRestId: string | undefined
   let propsDestructureRestId: string | undefined
   let propsTypeDecl: PropsDeclType | undefined
   let propsTypeDecl: PropsDeclType | undefined
@@ -534,15 +534,9 @@ export function compileScript(
           node.callee
           node.callee
         )
         )
       }
       }
-      propsRuntimeDefaults = node.arguments[1] as ObjectExpression
-      if (
-        !propsRuntimeDefaults ||
-        propsRuntimeDefaults.type !== 'ObjectExpression'
-      ) {
-        error(
-          `The 2nd argument of ${WITH_DEFAULTS} must be an object literal.`,
-          propsRuntimeDefaults || node
-        )
+      propsRuntimeDefaults = node.arguments[1]
+      if (!propsRuntimeDefaults) {
+        error(`The 2nd argument of ${WITH_DEFAULTS} is required.`, node)
       }
       }
     } else {
     } else {
       error(
       error(
@@ -872,7 +866,9 @@ export function compileScript(
             destructured.needSkipFactory ? `, skipFactory: true` : ``
             destructured.needSkipFactory ? `, skipFactory: true` : ``
           }`
           }`
         } else if (hasStaticDefaults) {
         } else if (hasStaticDefaults) {
-          const prop = propsRuntimeDefaults!.properties.find(node => {
+          const prop = (
+            propsRuntimeDefaults as ObjectExpression
+          ).properties.find(node => {
             if (node.type === 'SpreadElement') return false
             if (node.type === 'SpreadElement') return false
             return resolveObjectKey(node.key, node.computed) === key
             return resolveObjectKey(node.key, node.computed) === key
           }) as ObjectProperty | ObjectMethod
           }) as ObjectProperty | ObjectMethod
@@ -1001,7 +997,7 @@ export function compileScript(
           m.key.type === 'Identifier'
           m.key.type === 'Identifier'
         ) {
         ) {
           if (
           if (
-            propsRuntimeDefaults!.properties.some(p => {
+            (propsRuntimeDefaults as ObjectExpression).properties.some(p => {
               if (p.type === 'SpreadElement') return false
               if (p.type === 'SpreadElement') return false
               return (
               return (
                 resolveObjectKey(p.key, p.computed) ===
                 resolveObjectKey(p.key, p.computed) ===