]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
feat(compiler-sfc): codegen support for defineEmits() short syntax (followup of ...
authorEvan You <yyx990803@gmail.com>
Thu, 30 Mar 2023 11:59:07 +0000 (19:59 +0800)
committerEvan You <yyx990803@gmail.com>
Thu, 30 Mar 2023 11:59:07 +0000 (19:59 +0800)
packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap
packages/compiler-sfc/__tests__/compileScript.spec.ts
packages/compiler-sfc/src/compileScript.ts

index e78522ee3af165fa1ab9d997c87986b8173ca406..da223439c5712aa01557a7d29cb29e02fe8ddc0d 100644 (file)
@@ -1478,6 +1478,22 @@ export default /*#__PURE__*/_defineComponent({
 
       
       
+return { emit }
+}
+
+})"
+`;
+
+exports[`SFC compile <script setup> > with TypeScript > defineEmits w/ type (tuple syntax) 1`] = `
+"import { defineComponent as _defineComponent } from 'vue'
+
+export default /*#__PURE__*/_defineComponent({
+  emits: [\\"foo\\", \\"bar\\"],
+  setup(__props, { expose: __expose, emit }: { emit: ({ foo: [], bar: [] }), expose: any, slots: any, attrs: any }) {
+  __expose();
+
+      
+      
 return { emit }
 }
 
index 11d1bc02f9cc58cbbfb90d83ee4180b8d6712e1a..5b223555e194cf0dc22421e96aa45cb1983f0845 100644 (file)
@@ -1540,6 +1540,16 @@ const emit = defineEmits(['a', 'b'])
       expect(content).toMatch(`emits: ['foo']`)
     })
 
+    test('defineEmits w/ type (tuple syntax)', () => {
+      const { content } = compile(`
+      <script setup lang="ts">
+      const emit = defineEmits<{ foo: [], bar: [] }>()
+      </script>
+      `)
+      expect(content).toMatch(`emits: ["foo", "bar"]`)
+      assertCode(content)
+    })
+
     test('runtime Enum', () => {
       const { content, bindings } = compile(
         `<script setup lang="ts">
@@ -1871,6 +1881,19 @@ const emit = defineEmits(['a', 'b'])
         </script>`).content
       )
     })
+
+    test('mixed usage of tuple / call signature in defineEmits', () => {
+      expect(() =>
+        compile(`<script setup lang="ts">
+        defineEmits<{
+          foo: []
+          (e: 'hi'): void
+        }>()
+        </script>`)
+      ).toThrow(
+        `defineEmits() type cannot mixed call signature and property syntax.`
+      )
+    })
   })
 })
 
index 9a5e19c84d41d64ed269135618fb08087fc9b13c..2c2505740a7bcfce4aa4dc4ee20b8d58561a2618 100644 (file)
@@ -1486,7 +1486,7 @@ export function compileScript(
     extractRuntimeProps(propsTypeDecl, typeDeclaredProps, declaredTypes)
   }
   if (emitsTypeDecl) {
-    extractRuntimeEmits(emitsTypeDecl, typeDeclaredEmits)
+    extractRuntimeEmits(emitsTypeDecl, typeDeclaredEmits, error)
   }
 
   // 5. check macro args to make sure it doesn't reference setup scope
@@ -2289,15 +2289,32 @@ function inferValueType(node: Node): string | undefined {
 
 function extractRuntimeEmits(
   node: TSFunctionType | TSTypeLiteral | TSInterfaceBody,
-  emits: Set<string>
+  emits: Set<string>,
+  error: (msg: string, node: Node) => never
 ) {
   if (node.type === 'TSTypeLiteral' || node.type === 'TSInterfaceBody') {
     const members = node.type === 'TSTypeLiteral' ? node.members : node.body
+    let hasCallSignature = false
+    let hasProperty = false
     for (let t of members) {
       if (t.type === 'TSCallSignatureDeclaration') {
         extractEventNames(t.parameters[0], emits)
+        hasCallSignature = true
+      }
+      if (t.type === 'TSPropertySignature') {
+        if (t.key.type !== 'Identifier' || t.computed) {
+          error(`defineEmits() type cannot use computed keys.`, t.key)
+        }
+        emits.add(t.key.name)
+        hasProperty = true
       }
     }
+    if (hasCallSignature && hasProperty) {
+      error(
+        `defineEmits() type cannot mixed call signature and property syntax.`,
+        node
+      )
+    }
     return
   } else {
     extractEventNames(node.parameters[0], emits)