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

fix(compiler-sfc): skip empty `defineOptions` and support TypeScript type assertions (#8028)

三咲智子 Kevin Deng 3 лет назад
Родитель
Сommit
955752951e

+ 14 - 1
packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap

@@ -658,12 +658,25 @@ exports[`SFC compile <script setup> > defineOptions() > basic usage 1`] = `
   setup(__props, { expose: __expose }) {
   __expose();
 
+        
+        
+return {  }
+}
+
+})"
+`;
 
+exports[`SFC compile <script setup> > defineOptions() > empty argument 1`] = `
+"export default {
+  setup(__props, { expose: __expose }) {
+  __expose();
 
+        
+        
 return {  }
 }
 
-})"
+}"
 `;
 
 exports[`SFC compile <script setup> > defineProps w/ external definition 1`] = `

+ 49 - 5
packages/compiler-sfc/__tests__/compileScript.spec.ts

@@ -133,7 +133,7 @@ const myEmit = defineEmits(['foo', 'bar'])
     expect(bindings).toStrictEqual({
       myEmit: BindingTypes.SETUP_CONST
     })
-    // should remove defineOptions import and call
+    // should remove defineEmits import and call
     expect(content).not.toMatch('defineEmits')
     // should generate correct setup signature
     expect(content).toMatch(
@@ -205,10 +205,10 @@ const myEmit = defineEmits(['foo', 'bar'])
   describe('defineOptions()', () => {
     test('basic usage', () => {
       const { content } = compile(`
-<script setup>
-defineOptions({ name: 'FooApp' })
-</script>
-  `)
+        <script setup>
+        defineOptions({ name: 'FooApp' })
+        </script>
+      `)
       assertCode(content)
       // should remove defineOptions import and call
       expect(content).not.toMatch('defineOptions')
@@ -218,6 +218,18 @@ defineOptions({ name: 'FooApp' })
       )
     })
 
+    test('empty argument', () => {
+      const { content } = compile(`
+        <script setup>
+        defineOptions()
+        </script>
+      `)
+      assertCode(content)
+      expect(content).toMatch(`export default {`)
+      // should remove defineOptions import and call
+      expect(content).not.toMatch('defineOptions')
+    })
+
     it('should emit an error with two defineProps', () => {
       expect(() =>
         compile(`
@@ -249,6 +261,26 @@ defineOptions({ name: 'FooApp' })
       ).toThrowError(
         '[@vue/compiler-sfc] defineOptions() cannot be used to declare emits. Use defineEmits() instead.'
       )
+
+      expect(() =>
+        compile(`
+        <script setup>
+        defineOptions({ expose: ['foo'] })
+        </script>
+      `)
+      ).toThrowError(
+        '[@vue/compiler-sfc] defineOptions() cannot be used to declare expose. Use defineExpose() instead.'
+      )
+
+      expect(() =>
+        compile(`
+        <script setup>
+        defineOptions({ slots: ['foo'] })
+        </script>
+      `)
+      ).toThrowError(
+        '[@vue/compiler-sfc] defineOptions() cannot be used to declare slots. Use defineSlots() instead.'
+      )
     })
 
     it('should emit an error with type generic', () => {
@@ -262,6 +294,18 @@ defineOptions({ name: 'FooApp' })
         '[@vue/compiler-sfc] defineOptions() cannot accept type arguments'
       )
     })
+
+    it('should emit an error with type assertion', () => {
+      expect(() =>
+        compile(`
+        <script setup lang="ts">
+        defineOptions({ props: [] } as any)
+        </script>
+        `)
+      ).toThrowError(
+        '[@vue/compiler-sfc] defineOptions() cannot be used to declare props. Use defineProps() instead.'
+      )
+    })
   })
 
   test('defineExpose()', () => {

+ 2 - 1
packages/compiler-sfc/src/compileScript.ts

@@ -702,9 +702,10 @@ export function compileScript(
     if (node.typeParameters) {
       error(`${DEFINE_OPTIONS}() cannot accept type arguments`, node)
     }
+    if (!node.arguments[0]) return true
 
     hasDefineOptionsCall = true
-    optionsRuntimeDecl = node.arguments[0]
+    optionsRuntimeDecl = unwrapTSNode(node.arguments[0])
 
     let propsOption = undefined
     let emitsOption = undefined