]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
test: split compileScript macro tests
authorEvan You <yyx990803@gmail.com>
Wed, 12 Apr 2023 08:46:26 +0000 (16:46 +0800)
committerEvan You <yyx990803@gmail.com>
Wed, 12 Apr 2023 08:46:26 +0000 (16:46 +0800)
21 files changed:
packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap
packages/compiler-sfc/__tests__/__snapshots__/compileScriptPropsTransform.spec.ts.snap [deleted file]
packages/compiler-sfc/__tests__/compileScript.spec.ts
packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineEmits.spec.ts.snap [new file with mode: 0644]
packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineExpose.spec.ts.snap [new file with mode: 0644]
packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineModel.spec.ts.snap [new file with mode: 0644]
packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineOptions.spec.ts.snap [new file with mode: 0644]
packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineProps.spec.ts.snap [new file with mode: 0644]
packages/compiler-sfc/__tests__/compileScript/__snapshots__/definePropsDestructure.spec.ts.snap [moved from packages/compiler-sfc/__tests__/__snapshots__/compileScriptPropsDestructure.spec.ts.snap with 100% similarity]
packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineSlots.spec.ts.snap [new file with mode: 0644]
packages/compiler-sfc/__tests__/compileScript/__snapshots__/hoistStatic.spec.ts.snap [moved from packages/compiler-sfc/__tests__/__snapshots__/compileScriptHoistStatic.spec.ts.snap with 100% similarity]
packages/compiler-sfc/__tests__/compileScript/__snapshots__/reactivityTransform.spec.ts.snap [moved from packages/compiler-sfc/__tests__/__snapshots__/compileScriptRefTransform.spec.ts.snap with 100% similarity]
packages/compiler-sfc/__tests__/compileScript/defineEmits.spec.ts [new file with mode: 0644]
packages/compiler-sfc/__tests__/compileScript/defineExpose.spec.ts [new file with mode: 0644]
packages/compiler-sfc/__tests__/compileScript/defineModel.spec.ts [new file with mode: 0644]
packages/compiler-sfc/__tests__/compileScript/defineOptions.spec.ts [new file with mode: 0644]
packages/compiler-sfc/__tests__/compileScript/defineProps.spec.ts [new file with mode: 0644]
packages/compiler-sfc/__tests__/compileScript/definePropsDestructure.spec.ts [moved from packages/compiler-sfc/__tests__/compileScriptPropsDestructure.spec.ts with 99% similarity]
packages/compiler-sfc/__tests__/compileScript/defineSlots.spec.ts [new file with mode: 0644]
packages/compiler-sfc/__tests__/compileScript/hoistStatic.spec.ts [moved from packages/compiler-sfc/__tests__/compileScriptHoistStatic.spec.ts with 97% similarity]
packages/compiler-sfc/__tests__/compileScript/reactivityTransform.spec.ts [moved from packages/compiler-sfc/__tests__/compileScriptRefTransform.spec.ts with 98% similarity]

index 9280aee88dd9a007847cd6b4e2bacb15b1a082a7..18b5d90eaf60352c43e9969934f05f6fb49994d4 100644 (file)
@@ -44,21 +44,6 @@ return { a }
 })"
 `;
 
-exports[`SFC compile <script setup> > <script> after <script setup> the script content not end with \`\\n\` 1`] = `
-"import { x } from './x'
-    const n = 1
-
-export default {
-  setup(__props, { expose: __expose }) {
-  __expose();
-
-    
-return { n, get x() { return x } }
-}
-
-}"
-`;
-
 exports[`SFC compile <script setup> > <script> and <script setup> co-usage > export call expression as default 1`] = `
 "function fn() {
         return \\"hello, world\\";
@@ -627,207 +612,6 @@ return { foo, bar, baz, y, z }
 }"
 `;
 
-exports[`SFC compile <script setup> > defineEmits() 1`] = `
-"export default {
-  emits: ['foo', 'bar'],
-  setup(__props, { expose: __expose, emit: myEmit }) {
-  __expose();
-
-
-
-return { myEmit }
-}
-
-}"
-`;
-
-exports[`SFC compile <script setup> > defineExpose() 1`] = `
-"export default {
-  setup(__props, { expose: __expose }) {
-
-__expose({ foo: 123 })
-
-return {  }
-}
-
-}"
-`;
-
-exports[`SFC compile <script setup> > defineModel() > basic usage 1`] = `
-"import { useModel as _useModel } from 'vue'
-
-export default {
-  props: {
-    \\"modelValue\\": { required: true },
-    \\"count\\": {},
-  },
-  emits: [\\"update:modelValue\\", \\"update:count\\"],
-  setup(__props, { expose: __expose }) {
-  __expose();
-
-        const modelValue = _useModel(__props, \\"modelValue\\")
-        const c = _useModel(__props, \\"count\\")
-        
-return { modelValue, c }
-}
-
-}"
-`;
-
-exports[`SFC compile <script setup> > defineModel() > w/ array props 1`] = `
-"import { useModel as _useModel, mergeModels as _mergeModels } from 'vue'
-
-export default {
-  props: _mergeModels(['foo', 'bar'], {
-    \\"count\\": {},
-  }),
-  emits: [\\"update:count\\"],
-  setup(__props, { expose: __expose }) {
-  __expose();
-
-        
-        const count = _useModel(__props, \\"count\\")
-        
-return { count }
-}
-
-}"
-`;
-
-exports[`SFC compile <script setup> > defineModel() > w/ defineProps and defineEmits 1`] = `
-"import { useModel as _useModel, mergeModels as _mergeModels } from 'vue'
-
-export default {
-  props: _mergeModels({ foo: String }, {
-    \\"modelValue\\": { default: 0 },
-  }),
-  emits: _mergeModels(['change'], [\\"update:modelValue\\"]),
-  setup(__props, { expose: __expose }) {
-  __expose();
-
-        
-        
-        const count = _useModel(__props, \\"modelValue\\")
-        
-return { count }
-}
-
-}"
-`;
-
-exports[`SFC compile <script setup> > defineModel() > w/ local flag 1`] = `
-"import { useModel as _useModel } from 'vue'
-const local = true
-        
-export default {
-  props: {
-    \\"modelValue\\": { local: true, default: 1 },
-    \\"bar\\": { [key]: true },
-    \\"baz\\": { ...x },
-    \\"qux\\": x,
-    \\"foo2\\": { local: true, ...x },
-    \\"hoist\\": { local },
-  },
-  emits: [\\"update:modelValue\\", \\"update:bar\\", \\"update:baz\\", \\"update:qux\\", \\"update:foo2\\", \\"update:hoist\\"],
-  setup(__props, { expose: __expose }) {
-  __expose();
-
-        const foo = _useModel(__props, \\"modelValue\\", { local: true })
-        const bar = _useModel(__props, \\"bar\\", { [key]: true })
-        const baz = _useModel(__props, \\"baz\\", { ...x })
-        const qux = _useModel(__props, \\"qux\\", x)
-
-        const foo2 = _useModel(__props, \\"foo2\\", { local: true })
-
-        const hoist = _useModel(__props, \\"hoist\\", { local })
-        
-return { foo, bar, baz, qux, foo2, local, hoist }
-}
-
-}"
-`;
-
-exports[`SFC compile <script setup> > defineOptions() > basic usage 1`] = `
-"export default /*#__PURE__*/Object.assign({ name: 'FooApp' }, {
-  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`] = `
-"import { propsModel } from './props'
-    
-export default {
-  props: propsModel,
-  setup(__props, { expose: __expose }) {
-  __expose();
-
-const props = __props;
-
-    
-    
-return { props, get propsModel() { return propsModel } }
-}
-
-}"
-`;
-
-exports[`SFC compile <script setup> > defineProps w/ leading code 1`] = `
-"import { x } from './x'
-    
-export default {
-  props: {},
-  setup(__props, { expose: __expose }) {
-  __expose();
-
-const props = __props;
-
-    
-return { props, get x() { return x } }
-}
-
-}"
-`;
-
-exports[`SFC compile <script setup> > defineProps() 1`] = `
-"const bar = 1
-
-export default {
-  props: {
-  foo: String
-},
-  setup(__props, { expose: __expose }) {
-  __expose();
-
-const props = __props;
-
-
-
-return { props, bar }
-}
-
-}"
-`;
-
 exports[`SFC compile <script setup> > defineProps/defineEmits in multi-variable declaration (full removal) 1`] = `
 "export default {
   props: ['item'],
@@ -1489,578 +1273,62 @@ return { Foo }
 })"
 `;
 
-exports[`SFC compile <script setup> > with TypeScript > defineEmits w/ type (exported interface) 1`] = `
-"import { defineComponent as _defineComponent } from 'vue'
-export interface Emits { (e: 'foo' | 'bar'): void }
-      
-export default /*#__PURE__*/_defineComponent({
-  emits: [\\"foo\\", \\"bar\\"],
-  setup(__props, { expose: __expose, emit }) {
-  __expose();
-
-      
-      
-return { emit }
-}
-
-})"
-`;
-
-exports[`SFC compile <script setup> > with TypeScript > defineEmits w/ type (exported type alias) 1`] = `
-"import { defineComponent as _defineComponent } from 'vue'
-export type Emits = { (e: 'foo' | 'bar'): void }
-      
-export default /*#__PURE__*/_defineComponent({
-  emits: [\\"foo\\", \\"bar\\"],
-  setup(__props, { expose: __expose, emit }) {
-  __expose();
-
-      
-      
-return { emit }
-}
-
-})"
-`;
-
-exports[`SFC compile <script setup> > with TypeScript > defineEmits w/ type (interface ts type) 1`] = `
-"import { defineComponent as _defineComponent } from 'vue'
-interface Emits { (e: 'foo'): void }
-      
-export default /*#__PURE__*/_defineComponent({
-  emits: ['foo'],
-  setup(__props, { expose: __expose, emit }) {
-  __expose();
-
-      
-      
-return { emit }
-}
-
-})"
-`;
-
-exports[`SFC compile <script setup> > with TypeScript > defineEmits w/ type (interface) 1`] = `
+exports[`SFC compile <script setup> > with TypeScript > hoist type declarations 1`] = `
 "import { defineComponent as _defineComponent } from 'vue'
-interface Emits { (e: 'foo' | 'bar'): void }
-      
-export default /*#__PURE__*/_defineComponent({
-  emits: [\\"foo\\", \\"bar\\"],
-  setup(__props, { expose: __expose, emit }) {
-  __expose();
-
-      
+export interface Foo {}
+        type Bar = {}
       
-return { emit }
-}
-
-})"
-`;
-
-exports[`SFC compile <script setup> > with TypeScript > defineEmits w/ type (property syntax string literal) 1`] = `
-"import { defineComponent as _defineComponent } from 'vue'
-
 export default /*#__PURE__*/_defineComponent({
-  emits: [\\"foo:bar\\"],
-  setup(__props, { expose: __expose, emit }) {
+  setup(__props, { expose: __expose }) {
   __expose();
 
-      
-      
-return { emit }
+        
+return {  }
 }
 
 })"
 `;
 
-exports[`SFC compile <script setup> > with TypeScript > defineEmits w/ type (property syntax) 1`] = `
+exports[`SFC compile <script setup> > with TypeScript > import type 1`] = `
 "import { defineComponent as _defineComponent } from 'vue'
-
+import type { Foo } from './main.ts'
+        import { type Bar, Baz } from './main.ts'
+        
 export default /*#__PURE__*/_defineComponent({
-  emits: [\\"foo\\", \\"bar\\"],
-  setup(__props, { expose: __expose, emit }) {
+  setup(__props, { expose: __expose }) {
   __expose();
 
-      
-      
-return { emit }
+        
+return { get Baz() { return Baz } }
 }
 
 })"
 `;
 
-exports[`SFC compile <script setup> > with TypeScript > defineEmits w/ type (referenced exported function type) 1`] = `
+exports[`SFC compile <script setup> > with TypeScript > runtime Enum 1`] = `
 "import { defineComponent as _defineComponent } from 'vue'
-export type Emits = (e: 'foo' | 'bar') => void
-      
+enum Foo { A = 123 }
+        
 export default /*#__PURE__*/_defineComponent({
-  emits: [\\"foo\\", \\"bar\\"],
-  setup(__props, { expose: __expose, emit }) {
+  setup(__props, { expose: __expose }) {
   __expose();
 
-      
-      
-return { emit }
+        
+return { Foo }
 }
 
 })"
 `;
 
-exports[`SFC compile <script setup> > with TypeScript > defineEmits w/ type (referenced function type) 1`] = `
+exports[`SFC compile <script setup> > with TypeScript > runtime Enum in normal script 1`] = `
 "import { defineComponent as _defineComponent } from 'vue'
-type Emits = (e: 'foo' | 'bar') => void
-      
-export default /*#__PURE__*/_defineComponent({
-  emits: [\\"foo\\", \\"bar\\"],
-  setup(__props, { expose: __expose, emit }) {
-  __expose();
-
-      
-      
-return { emit }
-}
-
-})"
-`;
 
-exports[`SFC compile <script setup> > with TypeScript > defineEmits w/ type (type alias) 1`] = `
-"import { defineComponent as _defineComponent } from 'vue'
-type Emits = { (e: 'foo' | 'bar'): void }
-      
+          export enum D { D = \\"D\\" }
+          const enum C { C = \\"C\\" }
+          enum B { B = \\"B\\" }
+        
 export default /*#__PURE__*/_defineComponent({
-  emits: [\\"foo\\", \\"bar\\"],
-  setup(__props, { expose: __expose, emit }) {
-  __expose();
-
-      
-      
-return { emit }
-}
-
-})"
-`;
-
-exports[`SFC compile <script setup> > with TypeScript > defineEmits w/ type (type literal w/ call signatures) 1`] = `
-"import { defineComponent as _defineComponent } from 'vue'
-
-export default /*#__PURE__*/_defineComponent({
-  emits: [\\"foo\\", \\"bar\\", \\"baz\\"],
-  setup(__props, { expose: __expose, emit }) {
-  __expose();
-
-      
-      
-return { emit }
-}
-
-})"
-`;
-
-exports[`SFC compile <script setup> > with TypeScript > defineEmits w/ type 1`] = `
-"import { defineComponent as _defineComponent } from 'vue'
-
-export default /*#__PURE__*/_defineComponent({
-  emits: [\\"foo\\", \\"bar\\"],
-  setup(__props, { expose: __expose, emit }) {
-  __expose();
-
-      
-      
-return { emit }
-}
-
-})"
-`;
-
-exports[`SFC compile <script setup> > with TypeScript > defineEmits w/ type from normal script 1`] = `
-"import { defineComponent as _defineComponent } from 'vue'
-
-        export interface Emits { (e: 'foo' | 'bar'): void }
-      
-export default /*#__PURE__*/_defineComponent({
-  emits: [\\"foo\\", \\"bar\\"],
-  setup(__props, { expose: __expose, emit }) {
-  __expose();
-
-      
-      
-return { emit }
-}
-
-})"
-`;
-
-exports[`SFC compile <script setup> > with TypeScript > defineModel() > basic usage 1`] = `
-"import { useModel as _useModel, defineComponent as _defineComponent } from 'vue'
-
-export default /*#__PURE__*/_defineComponent({
-  props: {
-    \\"modelValue\\": { type: [Boolean, String] },
-    \\"count\\": { type: Number },
-    \\"disabled\\": { type: Number, ...{ required: false } },
-    \\"any\\": { type: Boolean, skipCheck: true },
-  },
-  emits: [\\"update:modelValue\\", \\"update:count\\", \\"update:disabled\\", \\"update:any\\"],
-  setup(__props, { expose: __expose }) {
-  __expose();
-
-          const modelValue = _useModel(__props, \\"modelValue\\")
-          const count = _useModel(__props, \\"count\\")
-          const disabled = _useModel(__props, \\"disabled\\")
-          const any = _useModel(__props, \\"any\\")
-          
-return { modelValue, count, disabled, any }
-}
-
-})"
-`;
-
-exports[`SFC compile <script setup> > with TypeScript > defineModel() > w/ production mode 1`] = `
-"import { useModel as _useModel, defineComponent as _defineComponent } from 'vue'
-
-export default /*#__PURE__*/_defineComponent({
-  props: {
-    \\"modelValue\\": { type: Boolean },
-    \\"fn\\": {},
-    \\"fnWithDefault\\": { type: Function, ...{ default: () => null } },
-    \\"str\\": {},
-    \\"optional\\": { required: false },
-  },
-  emits: [\\"update:modelValue\\", \\"update:fn\\", \\"update:fnWithDefault\\", \\"update:str\\", \\"update:optional\\"],
-  setup(__props, { expose: __expose }) {
-  __expose();
-
-          const modelValue = _useModel(__props, \\"modelValue\\")
-          const fn = _useModel(__props, \\"fn\\")
-          const fnWithDefault = _useModel(__props, \\"fnWithDefault\\")
-          const str = _useModel(__props, \\"str\\")
-          const optional = _useModel(__props, \\"optional\\")
-          
-return { modelValue, fn, fnWithDefault, str, optional }
-}
-
-})"
-`;
-
-exports[`SFC compile <script setup> > with TypeScript > defineProps w/ TS assertion 1`] = `
-"import { defineComponent as _defineComponent } from 'vue'
-
-export default /*#__PURE__*/_defineComponent({
-  props: ['foo'],
-  setup(__props, { expose: __expose }) {
-  __expose();
-
-        
-      
-return {  }
-}
-
-})"
-`;
-
-exports[`SFC compile <script setup> > with TypeScript > defineProps w/ exported interface 1`] = `
-"import { defineComponent as _defineComponent } from 'vue'
-export interface Props { x?: number }
-      
-export default /*#__PURE__*/_defineComponent({
-  props: {
-    x: { type: Number, required: false }
-  },
-  setup(__props: any, { expose: __expose }) {
-  __expose();
-
-      
-      
-return {  }
-}
-
-})"
-`;
-
-exports[`SFC compile <script setup> > with TypeScript > defineProps w/ exported interface in normal script 1`] = `
-"import { defineComponent as _defineComponent } from 'vue'
-
-        export interface Props { x?: number }
-      
-export default /*#__PURE__*/_defineComponent({
-  props: {
-    x: { type: Number, required: false }
-  },
-  setup(__props: any, { expose: __expose }) {
-  __expose();
-
-        
-      
-return {  }
-}
-
-})"
-`;
-
-exports[`SFC compile <script setup> > with TypeScript > defineProps w/ exported type alias 1`] = `
-"import { defineComponent as _defineComponent } from 'vue'
-export type Props = { x?: number }
-      
-export default /*#__PURE__*/_defineComponent({
-  props: {
-    x: { type: Number, required: false }
-  },
-  setup(__props: any, { expose: __expose }) {
-  __expose();
-
-      
-      
-return {  }
-}
-
-})"
-`;
-
-exports[`SFC compile <script setup> > with TypeScript > defineProps w/ extends interface 1`] = `
-"import { defineComponent as _defineComponent } from 'vue'
-interface Bar extends Foo { y?: number }
-        interface Props extends Bar {
-          z: number
-          y: string
-        }
-        
-        interface Foo { x?: number }
-      
-export default /*#__PURE__*/_defineComponent({
-  props: {
-    z: { type: Number, required: true },
-    y: { type: String, required: true },
-    x: { type: Number, required: false }
-  },
-  setup(__props: any, { expose: __expose }) {
-  __expose();
-
-        
-      
-return {  }
-}
-
-})"
-`;
-
-exports[`SFC compile <script setup> > with TypeScript > defineProps w/ interface 1`] = `
-"import { defineComponent as _defineComponent } from 'vue'
-interface Props { x?: number }
-      
-export default /*#__PURE__*/_defineComponent({
-  props: {
-    x: { type: Number, required: false }
-  },
-  setup(__props: any, { expose: __expose }) {
-  __expose();
-
-      
-      
-return {  }
-}
-
-})"
-`;
-
-exports[`SFC compile <script setup> > with TypeScript > defineProps w/ type 1`] = `
-"import { defineComponent as _defineComponent } from 'vue'
-interface Test {}
-
-      type Alias = number[]
-
-      
-export default /*#__PURE__*/_defineComponent({
-  props: {
-    string: { type: String, required: true },
-    number: { type: Number, required: true },
-    boolean: { type: Boolean, required: true },
-    object: { type: Object, required: true },
-    objectLiteral: { type: Object, required: true },
-    fn: { type: Function, required: true },
-    functionRef: { type: Function, required: true },
-    objectRef: { type: Object, required: true },
-    dateTime: { type: Date, required: true },
-    array: { type: Array, required: true },
-    arrayRef: { type: Array, required: true },
-    tuple: { type: Array, required: true },
-    set: { type: Set, required: true },
-    literal: { type: String, required: true },
-    optional: { type: null, required: false },
-    recordRef: { type: Object, required: true },
-    interface: { type: Object, required: true },
-    alias: { type: Array, required: true },
-    method: { type: Function, required: true },
-    symbol: { type: Symbol, required: true },
-    extract: { type: Number, required: true },
-    exclude: { type: [Number, Boolean], required: true },
-    uppercase: { type: String, required: true },
-    params: { type: Array, required: true },
-    nonNull: { type: String, required: true },
-    objectOrFn: { type: [Function, Object], required: true },
-    union: { type: [String, Number], required: true },
-    literalUnion: { type: String, required: true },
-    literalUnionNumber: { type: Number, required: true },
-    literalUnionMixed: { type: [String, Number, Boolean], required: true },
-    intersection: { type: Object, required: true },
-    intersection2: { type: String, required: true },
-    foo: { type: [Function, null], required: true },
-    unknown: { type: null, required: true },
-    unknownUnion: { type: null, required: true },
-    unknownIntersection: { type: Object, required: true },
-    unknownUnionWithBoolean: { type: Boolean, required: true, skipCheck: true },
-    unknownUnionWithFunction: { type: Function, required: true, skipCheck: true }
-  },
-  setup(__props: any, { expose: __expose }) {
-  __expose();
-
-      
-      
-return {  }
-}
-
-})"
-`;
-
-exports[`SFC compile <script setup> > with TypeScript > defineProps w/ type alias 1`] = `
-"import { defineComponent as _defineComponent } from 'vue'
-type Props = { x?: number }
-      
-export default /*#__PURE__*/_defineComponent({
-  props: {
-    x: { type: Number, required: false }
-  },
-  setup(__props: any, { expose: __expose }) {
-  __expose();
-
-      
-      
-return {  }
-}
-
-})"
-`;
-
-exports[`SFC compile <script setup> > with TypeScript > defineProps/Emit w/ runtime options 1`] = `
-"import { defineComponent as _defineComponent } from 'vue'
-
-export default /*#__PURE__*/_defineComponent({
-  props: { foo: String },
-  emits: ['a', 'b'],
-  setup(__props, { expose: __expose, emit }) {
-  __expose();
-
-const props = __props;
-
-
-
-
-return { props, emit }
-}
-
-})"
-`;
-
-exports[`SFC compile <script setup> > with TypeScript > defineSlots() > basic usage 1`] = `
-"import { useSlots as _useSlots, defineComponent as _defineComponent } from 'vue'
-
-export default /*#__PURE__*/_defineComponent({
-  setup(__props, { expose: __expose }) {
-  __expose();
-
-          const slots = _useSlots()
-          
-return { slots }
-}
-
-})"
-`;
-
-exports[`SFC compile <script setup> > with TypeScript > defineSlots() > w/o generic params 1`] = `
-"import { useSlots as _useSlots } from 'vue'
-
-export default {
-  setup(__props, { expose: __expose }) {
-  __expose();
-
-          const slots = _useSlots()
-          
-return { slots }
-}
-
-}"
-`;
-
-exports[`SFC compile <script setup> > with TypeScript > defineSlots() > w/o return value 1`] = `
-"import { defineComponent as _defineComponent } from 'vue'
-
-export default /*#__PURE__*/_defineComponent({
-  setup(__props, { expose: __expose }) {
-  __expose();
-
-          
-          
-return {  }
-}
-
-})"
-`;
-
-exports[`SFC compile <script setup> > with TypeScript > hoist type declarations 1`] = `
-"import { defineComponent as _defineComponent } from 'vue'
-export interface Foo {}
-        type Bar = {}
-      
-export default /*#__PURE__*/_defineComponent({
-  setup(__props, { expose: __expose }) {
-  __expose();
-
-        
-return {  }
-}
-
-})"
-`;
-
-exports[`SFC compile <script setup> > with TypeScript > import type 1`] = `
-"import { defineComponent as _defineComponent } from 'vue'
-import type { Foo } from './main.ts'
-        import { type Bar, Baz } from './main.ts'
-        
-export default /*#__PURE__*/_defineComponent({
-  setup(__props, { expose: __expose }) {
-  __expose();
-
-        
-return { get Baz() { return Baz } }
-}
-
-})"
-`;
-
-exports[`SFC compile <script setup> > with TypeScript > runtime Enum 1`] = `
-"import { defineComponent as _defineComponent } from 'vue'
-enum Foo { A = 123 }
-        
-export default /*#__PURE__*/_defineComponent({
-  setup(__props, { expose: __expose }) {
-  __expose();
-
-        
-return { Foo }
-}
-
-})"
-`;
-
-exports[`SFC compile <script setup> > with TypeScript > runtime Enum in normal script 1`] = `
-"import { defineComponent as _defineComponent } from 'vue'
-
-          export enum D { D = \\"D\\" }
-          const enum C { C = \\"C\\" }
-          enum B { B = \\"B\\" }
-        
-export default /*#__PURE__*/_defineComponent({
-  setup(__props, { expose: __expose }) {
+  setup(__props, { expose: __expose }) {
   __expose();
 
         enum Foo { A = 123 }
@@ -2071,171 +1339,6 @@ return { D, C, B, Foo }
 })"
 `;
 
-exports[`SFC compile <script setup> > with TypeScript > withDefaults (dynamic) 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;
-
-      
-      
-return { props, get defaults() { return defaults } }
-}
-
-})"
-`;
-
-exports[`SFC compile <script setup> > with TypeScript > withDefaults (dynamic) w/ production mode 1`] = `
-"import { mergeDefaults as _mergeDefaults, defineComponent as _defineComponent } from 'vue'
-import { defaults } from './foo'
-      
-export default /*#__PURE__*/_defineComponent({
-  props: _mergeDefaults({
-    foo: { type: Function },
-    bar: { type: Boolean },
-    baz: { type: [Boolean, Function] },
-    qux: {}
-  }, { ...defaults }),
-  setup(__props: any, { expose: __expose }) {
-  __expose();
-
-const props = __props;
-
-      
-      
-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;
-
-      
-      
-return { props, get defaults() { return defaults } }
-}
-
-})"
-`;
-
-exports[`SFC compile <script setup> > with TypeScript > withDefaults (static) + normal script 1`] = `
-"import { defineComponent as _defineComponent } from 'vue'
-
-        interface Props {
-          a?: string;
-        }
-      
-export default /*#__PURE__*/_defineComponent({
-  props: {
-    a: { type: String, required: false, default: \\"a\\" }
-  },
-  setup(__props: any, { expose: __expose }) {
-  __expose();
-
-const props = __props;
-
-        
-      
-return { props }
-}
-
-})"
-`;
-
-exports[`SFC compile <script setup> > with TypeScript > withDefaults (static) 1`] = `
-"import { defineComponent as _defineComponent } from 'vue'
-
-export default /*#__PURE__*/_defineComponent({
-  props: {
-    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 } },
-    quux: { type: Function, required: false, default() { } },
-    quuxx: { type: Promise, required: false, async default() { return await Promise.resolve('hi') } },
-    fred: { type: String, required: false, get default() { return 'fred' } }
-  },
-  setup(__props: any, { expose: __expose }) {
-  __expose();
-
-const props = __props;
-
-      
-      
-return { props }
-}
-
-})"
-`;
-
-exports[`SFC compile <script setup> > with TypeScript > withDefaults (static) w/ production mode 1`] = `
-"import { defineComponent as _defineComponent } from 'vue'
-
-export default /*#__PURE__*/_defineComponent({
-  props: {
-    foo: {},
-    bar: { type: Boolean },
-    baz: { type: [Boolean, Function], default: true },
-    qux: { default: 'hi' }
-  },
-  setup(__props: any, { expose: __expose }) {
-  __expose();
-
-const props = __props;
-
-      
-      
-return { props }
-}
-
-})"
-`;
-
-exports[`SFC compile <script setup> > with TypeScript > withDefaults w/ dynamic object method 1`] = `
-"import { mergeDefaults as _mergeDefaults, defineComponent as _defineComponent } from 'vue'
-
-export default /*#__PURE__*/_defineComponent({
-  props: _mergeDefaults({
-    foo: { type: Function, required: false }
-  }, {
-        ['fo' + 'o']() { return 'foo' }
-      }),
-  setup(__props: any, { expose: __expose }) {
-  __expose();
-
-const props = __props;
-
-      
-      
-return { props }
-}
-
-})"
-`;
-
 exports[`SFC genDefaultAs > <script setup> only 1`] = `
 "const a = 1
       
diff --git a/packages/compiler-sfc/__tests__/__snapshots__/compileScriptPropsTransform.spec.ts.snap b/packages/compiler-sfc/__tests__/__snapshots__/compileScriptPropsTransform.spec.ts.snap
deleted file mode 100644 (file)
index 328f242..0000000
+++ /dev/null
@@ -1,230 +0,0 @@
-// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
-
-exports[`sfc props transform > $$() escape 1`] = `
-"import { toRef as _toRef } from 'vue'
-
-export default {
-  props: ['foo'],
-  setup(__props) {
-const __props_bar = _toRef(__props, 'bar');
-const __props_foo = _toRef(__props, 'foo');
-
-      
-      console.log((__props_foo))
-      console.log((__props_bar))
-      ;({ foo: __props_foo, baz: __props_bar })
-      
-return () => {}
-}
-
-}"
-`;
-
-exports[`sfc props transform > aliasing 1`] = `
-"import { toDisplayString as _toDisplayString } from \\"vue\\"
-
-
-export default {
-  props: ['foo'],
-  setup(__props) {
-
-      
-      let x = foo
-      let y = __props.foo
-      
-return (_ctx, _cache) => {
-  return _toDisplayString(__props.foo + __props.foo)
-}
-}
-
-}"
-`;
-
-exports[`sfc props transform > basic usage 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 > 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/ array runtime declaration 1`] = `
-"import { mergeDefaults as _mergeDefaults } from 'vue'
-
-export default {
-  props: _mergeDefaults(['foo', 'bar', 'baz'], {
-  foo: 1,
-  bar: () => ({}),
-  func: () => {}, __skip_func: true
-}),
-  setup(__props) {
-
-      
-      
-return () => {}
-}
-
-}"
-`;
-
-exports[`sfc props transform > default values w/ object runtime declaration 1`] = `
-"import { mergeDefaults as _mergeDefaults } from 'vue'
-
-export default {
-  props: _mergeDefaults({ foo: Number, bar: Object, func: Function, ext: null }, {
-  foo: 1,
-  bar: () => ({}),
-  func: () => {}, __skip_func: true,
-  ext: x, __skip_ext: true
-}),
-  setup(__props) {
-
-      
-      
-return () => {}
-}
-
-}"
-`;
-
-exports[`sfc props transform > default values w/ type declaration 1`] = `
-"import { defineComponent as _defineComponent } from 'vue'
-
-export default /*#__PURE__*/_defineComponent({
-  props: {
-    foo: { type: Number, required: false, default: 1 },
-    bar: { type: Object, required: false, default: () => ({}) },
-    func: { type: Function, required: false, default: () => {} }
-  },
-  setup(__props: any) {
-
-      
-      
-return () => {}
-}
-
-})"
-`;
-
-exports[`sfc props transform > default values w/ type declaration, prod mode 1`] = `
-"import { defineComponent as _defineComponent } from 'vue'
-
-export default /*#__PURE__*/_defineComponent({
-  props: {
-    foo: { default: 1 },
-    bar: { default: () => ({}) },
-    baz: null,
-    boola: { type: Boolean },
-    boolb: { type: [Boolean, Number] },
-    func: { type: Function, default: () => {} }
-  },
-  setup(__props: any) {
-
-      
-      
-return () => {}
-}
-
-})"
-`;
-
-exports[`sfc props transform > multiple variable declarations 1`] = `
-"import { toDisplayString as _toDisplayString, openBlock as _openBlock, createElementBlock as _createElementBlock } from \\"vue\\"
-
-
-export default {
-  props: ['foo'],
-  setup(__props) {
-
-      const bar = 'fish', hello = 'world'
-      
-return (_ctx, _cache) => {
-  return (_openBlock(), _createElementBlock(\\"div\\", null, _toDisplayString(__props.foo) + \\" \\" + _toDisplayString(hello) + \\" \\" + _toDisplayString(bar), 1 /* TEXT */))
-}
-}
-
-}"
-`;
-
-exports[`sfc props transform > nested scope 1`] = `
-"export default {
-  props: ['foo', 'bar'],
-  setup(__props) {
-
-      
-      function test(foo) {
-        console.log(foo)
-        console.log(__props.bar)
-      }
-      
-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'
-
-export default {
-  props: ['foo', 'bar', 'baz'],
-  setup(__props) {
-
-const rest = _createPropsRestProxy(__props, [\\"foo\\",\\"bar\\"]);
-
-      
-      
-return () => {}
-}
-
-}"
-`;
index 3daf46a51dd801a69d91dd135cde3467c65368c9..eec434758e8db2c19721771bf22e1f5d967e43dc 100644 (file)
@@ -68,82 +68,6 @@ describe('SFC compile <script setup>', () => {
     assertCode(content)
   })
 
-  test('defineProps()', () => {
-    const { content, bindings } = compile(`
-<script setup>
-const props = defineProps({
-  foo: String
-})
-const bar = 1
-</script>
-  `)
-    // should generate working code
-    assertCode(content)
-    // should analyze bindings
-    expect(bindings).toStrictEqual({
-      foo: BindingTypes.PROPS,
-      bar: BindingTypes.LITERAL_CONST,
-      props: BindingTypes.SETUP_REACTIVE_CONST
-    })
-
-    // should remove defineOptions import and call
-    expect(content).not.toMatch('defineProps')
-    // should generate correct setup signature
-    expect(content).toMatch(`setup(__props, { expose: __expose }) {`)
-    // should assign user identifier to it
-    expect(content).toMatch(`const props = __props`)
-    // should include context options in default export
-    expect(content).toMatch(`export default {
-  props: {
-  foo: String
-},`)
-  })
-
-  test('defineProps w/ external definition', () => {
-    const { content } = compile(`
-    <script setup>
-    import { propsModel } from './props'
-    const props = defineProps(propsModel)
-    </script>
-      `)
-    assertCode(content)
-    expect(content).toMatch(`export default {
-  props: propsModel,`)
-  })
-
-  // #4764
-  test('defineProps w/ leading code', () => {
-    const { content } = compile(`
-    <script setup>import { x } from './x'
-    const props = defineProps({})
-    </script>
-    `)
-    // props declaration should be inside setup, not moved along with the import
-    expect(content).not.toMatch(`const props = __props\nimport`)
-    assertCode(content)
-  })
-
-  test('defineEmits()', () => {
-    const { content, bindings } = compile(`
-<script setup>
-const myEmit = defineEmits(['foo', 'bar'])
-</script>
-  `)
-    assertCode(content)
-    expect(bindings).toStrictEqual({
-      myEmit: BindingTypes.SETUP_CONST
-    })
-    // should remove defineEmits import and call
-    expect(content).not.toMatch('defineEmits')
-    // should generate correct setup signature
-    expect(content).toMatch(
-      `setup(__props, { expose: __expose, emit: myEmit }) {`
-    )
-    // should include context options in default export
-    expect(content).toMatch(`export default {
-  emits: ['foo', 'bar'],`)
-  })
-
   test('defineProps/defineEmits in multi-variable declaration', () => {
     const { content } = compile(`
     <script setup>
@@ -202,282 +126,6 @@ const myEmit = defineEmits(['foo', 'bar'])
     expect(content).toMatch(`emits: ['a'],`)
   })
 
-  describe('defineOptions()', () => {
-    test('basic usage', () => {
-      const { content } = compile(`
-        <script setup>
-        defineOptions({ name: 'FooApp' })
-        </script>
-      `)
-      assertCode(content)
-      // should remove defineOptions import and call
-      expect(content).not.toMatch('defineOptions')
-      // should include context options in default export
-      expect(content).toMatch(
-        `export default /*#__PURE__*/Object.assign({ 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(`
-        <script setup>
-        defineOptions({ name: 'FooApp' })
-        defineOptions({ name: 'BarApp' })
-        </script>
-        `)
-      ).toThrowError('[@vue/compiler-sfc] duplicate defineOptions() call')
-    })
-
-    it('should emit an error with props or emits property', () => {
-      expect(() =>
-        compile(`
-        <script setup>
-        defineOptions({ props: { foo: String } })
-        </script>
-        `)
-      ).toThrowError(
-        '[@vue/compiler-sfc] defineOptions() cannot be used to declare props. Use defineProps() instead.'
-      )
-
-      expect(() =>
-        compile(`
-        <script setup>
-        defineOptions({ emits: ['update'] })
-        </script>
-      `)
-      ).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', () => {
-      expect(() =>
-        compile(`
-        <script setup lang="ts">
-        defineOptions<{ name: 'FooApp' }>()
-        </script>
-        `)
-      ).toThrowError(
-        '[@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.'
-      )
-    })
-
-    it('should emit an error with declaring props/emits/slots/expose', () => {
-      expect(() =>
-        compile(`
-          <script setup>
-          defineOptions({ props: ['foo'] })
-          </script>
-        `)
-      ).toThrowError(
-        '[@vue/compiler-sfc] defineOptions() cannot be used to declare props. Use defineProps() instead'
-      )
-
-      expect(() =>
-        compile(`
-          <script setup>
-          defineOptions({ emits: ['update'] })
-          </script>
-        `)
-      ).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 lang="ts">
-          defineOptions({ slots: Object })
-          </script>
-        `)
-      ).toThrowError(
-        '[@vue/compiler-sfc] defineOptions() cannot be used to declare slots. Use defineSlots() instead'
-      )
-    })
-  })
-
-  test('defineExpose()', () => {
-    const { content } = compile(`
-<script setup>
-defineExpose({ foo: 123 })
-</script>
-  `)
-    assertCode(content)
-    // should remove defineOptions import and call
-    expect(content).not.toMatch('defineExpose')
-    // should generate correct setup signature
-    expect(content).toMatch(`setup(__props, { expose: __expose }) {`)
-    // should replace callee
-    expect(content).toMatch(/\b__expose\(\{ foo: 123 \}\)/)
-  })
-
-  describe('defineModel()', () => {
-    test('basic usage', () => {
-      const { content, bindings } = compile(
-        `
-        <script setup>
-        const modelValue = defineModel({ required: true })
-        const c = defineModel('count')
-        </script>
-        `,
-        { defineModel: true }
-      )
-      assertCode(content)
-      expect(content).toMatch('props: {')
-      expect(content).toMatch('"modelValue": { required: true },')
-      expect(content).toMatch('"count": {},')
-      expect(content).toMatch('emits: ["update:modelValue", "update:count"],')
-      expect(content).toMatch(
-        `const modelValue = _useModel(__props, "modelValue")`
-      )
-      expect(content).toMatch(`const c = _useModel(__props, "count")`)
-      expect(content).toMatch(`return { modelValue, c }`)
-      expect(content).not.toMatch('defineModel')
-
-      expect(bindings).toStrictEqual({
-        modelValue: BindingTypes.SETUP_REF,
-        count: BindingTypes.PROPS,
-        c: BindingTypes.SETUP_REF
-      })
-    })
-
-    test('w/ defineProps and defineEmits', () => {
-      const { content, bindings } = compile(
-        `
-        <script setup>
-        defineProps({ foo: String })
-        defineEmits(['change'])
-        const count = defineModel({ default: 0 })
-        </script>
-      `,
-        { defineModel: true }
-      )
-      assertCode(content)
-      expect(content).toMatch(`props: _mergeModels({ foo: String }`)
-      expect(content).toMatch(`"modelValue": { default: 0 }`)
-      expect(content).toMatch(`const count = _useModel(__props, "modelValue")`)
-      expect(content).not.toMatch('defineModel')
-      expect(bindings).toStrictEqual({
-        count: BindingTypes.SETUP_REF,
-        foo: BindingTypes.PROPS,
-        modelValue: BindingTypes.PROPS
-      })
-    })
-
-    test('w/ array props', () => {
-      const { content, bindings } = compile(
-        `
-        <script setup>
-        defineProps(['foo', 'bar'])
-        const count = defineModel('count')
-        </script>
-      `,
-        { defineModel: true }
-      )
-      assertCode(content)
-      expect(content).toMatch(`props: _mergeModels(['foo', 'bar'], {
-    "count": {},
-  })`)
-      expect(content).toMatch(`const count = _useModel(__props, "count")`)
-      expect(content).not.toMatch('defineModel')
-      expect(bindings).toStrictEqual({
-        foo: BindingTypes.PROPS,
-        bar: BindingTypes.PROPS,
-        count: BindingTypes.SETUP_REF
-      })
-    })
-
-    test('w/ local flag', () => {
-      const { content } = compile(
-        `<script setup>
-        const foo = defineModel({ local: true, default: 1 })
-        const bar = defineModel('bar', { [key]: true })
-        const baz = defineModel('baz', { ...x })
-        const qux = defineModel('qux', x)
-
-        const foo2 = defineModel('foo2', { local: true, ...x })
-
-        const local = true
-        const hoist = defineModel('hoist', { local })
-        </script>`,
-        { defineModel: true }
-      )
-      assertCode(content)
-      expect(content).toMatch(
-        `_useModel(__props, "modelValue", { local: true })`
-      )
-      expect(content).toMatch(`_useModel(__props, "bar", { [key]: true })`)
-      expect(content).toMatch(`_useModel(__props, "baz", { ...x })`)
-      expect(content).toMatch(`_useModel(__props, "qux", x)`)
-      expect(content).toMatch(`_useModel(__props, "foo2", { local: true })`)
-      expect(content).toMatch(`_useModel(__props, "hoist", { local })`)
-    })
-  })
-
-  test('<script> after <script setup> the script content not end with `\\n`', () => {
-    const { content } = compile(`
-    <script setup>
-    import { x } from './x'
-    </script>
-    <script>const n = 1</script>
-    `)
-    assertCode(content)
-  })
-
   describe('<script> and <script setup> co-usage', () => {
     test('script first', () => {
       const { content } = compile(`
@@ -1168,739 +816,6 @@ defineExpose({ foo: 123 })
       assertCode(content)
     })
 
-    test('defineProps/Emit w/ runtime options', () => {
-      const { content } = compile(`
-<script setup lang="ts">
-const props = defineProps({ foo: String })
-const emit = defineEmits(['a', 'b'])
-</script>
-      `)
-      assertCode(content)
-      expect(content).toMatch(`export default /*#__PURE__*/_defineComponent({
-  props: { foo: String },
-  emits: ['a', 'b'],
-  setup(__props, { expose: __expose, emit }) {`)
-    })
-
-    test('defineProps w/ type', () => {
-      const { content, bindings } = compile(`
-      <script setup lang="ts">
-      interface Test {}
-
-      type Alias = number[]
-
-      defineProps<{
-        string: string
-        number: number
-        boolean: boolean
-        object: object
-        objectLiteral: { a: number }
-        fn: (n: number) => void
-        functionRef: Function
-        objectRef: Object
-        dateTime: Date
-        array: string[]
-        arrayRef: Array<any>
-        tuple: [number, number]
-        set: Set<string>
-        literal: 'foo'
-        optional?: any
-        recordRef: Record<string, null>
-        interface: Test
-        alias: Alias
-        method(): void
-        symbol: symbol
-        extract: Extract<1 | 2 | boolean, 2>
-        exclude: Exclude<1 | 2 | boolean, 2>
-        uppercase: Uppercase<'foo'>
-        params: Parameters<(foo: any) => void>
-        nonNull: NonNullable<string | null>
-        objectOrFn: {
-          (): void
-          foo: string
-        }
-
-        union: string | number
-        literalUnion: 'foo' | 'bar'
-        literalUnionNumber: 1 | 2 | 3 | 4 | 5
-        literalUnionMixed: 'foo' | 1 | boolean
-        intersection: Test & {}
-        intersection2: 'foo' & ('foo' | 'bar')
-        foo: ((item: any) => boolean) | null
-
-        unknown: UnknownType
-        unknownUnion: UnknownType | string
-        unknownIntersection: UnknownType & Object
-        unknownUnionWithBoolean: UnknownType | boolean
-        unknownUnionWithFunction: UnknownType | (() => any)
-      }>()
-      </script>`)
-      assertCode(content)
-      expect(content).toMatch(`string: { type: String, required: true }`)
-      expect(content).toMatch(`number: { type: Number, required: true }`)
-      expect(content).toMatch(`boolean: { type: Boolean, required: true }`)
-      expect(content).toMatch(`object: { type: Object, required: true }`)
-      expect(content).toMatch(`objectLiteral: { type: Object, required: true }`)
-      expect(content).toMatch(`fn: { type: Function, required: true }`)
-      expect(content).toMatch(`functionRef: { type: Function, required: true }`)
-      expect(content).toMatch(`objectRef: { type: Object, required: true }`)
-      expect(content).toMatch(`dateTime: { type: Date, required: true }`)
-      expect(content).toMatch(`array: { type: Array, required: true }`)
-      expect(content).toMatch(`arrayRef: { type: Array, required: true }`)
-      expect(content).toMatch(`tuple: { type: Array, required: true }`)
-      expect(content).toMatch(`set: { type: Set, required: true }`)
-      expect(content).toMatch(`literal: { type: String, required: true }`)
-      expect(content).toMatch(`optional: { type: null, required: false }`)
-      expect(content).toMatch(`recordRef: { type: Object, required: true }`)
-      expect(content).toMatch(`interface: { type: Object, required: true }`)
-      expect(content).toMatch(`alias: { type: Array, required: true }`)
-      expect(content).toMatch(`method: { type: Function, required: true }`)
-      expect(content).toMatch(`symbol: { type: Symbol, required: true }`)
-      expect(content).toMatch(
-        `objectOrFn: { type: [Function, Object], required: true },`
-      )
-      expect(content).toMatch(`extract: { type: Number, required: true }`)
-      expect(content).toMatch(
-        `exclude: { type: [Number, Boolean], required: true }`
-      )
-      expect(content).toMatch(`uppercase: { type: String, required: true }`)
-      expect(content).toMatch(`params: { type: Array, required: true }`)
-      expect(content).toMatch(`nonNull: { type: String, required: true }`)
-      expect(content).toMatch(
-        `union: { type: [String, Number], required: true }`
-      )
-      expect(content).toMatch(`literalUnion: { type: String, required: true }`)
-      expect(content).toMatch(
-        `literalUnionNumber: { type: Number, required: true }`
-      )
-      expect(content).toMatch(
-        `literalUnionMixed: { type: [String, Number, Boolean], required: true }`
-      )
-      expect(content).toMatch(`intersection: { type: Object, required: true }`)
-      expect(content).toMatch(`intersection2: { type: String, required: true }`)
-      expect(content).toMatch(`foo: { type: [Function, null], required: true }`)
-      expect(content).toMatch(`unknown: { type: null, required: true }`)
-      // uninon containing unknown type: skip check
-      expect(content).toMatch(`unknownUnion: { type: null, required: true }`)
-      // intersection containing unknown type: narrow to the known types
-      expect(content).toMatch(
-        `unknownIntersection: { type: Object, required: true },`
-      )
-      expect(content).toMatch(
-        `unknownUnionWithBoolean: { type: Boolean, required: true, skipCheck: true },`
-      )
-      expect(content).toMatch(
-        `unknownUnionWithFunction: { type: Function, required: true, skipCheck: true }`
-      )
-      expect(bindings).toStrictEqual({
-        string: BindingTypes.PROPS,
-        number: BindingTypes.PROPS,
-        boolean: BindingTypes.PROPS,
-        object: BindingTypes.PROPS,
-        objectLiteral: BindingTypes.PROPS,
-        fn: BindingTypes.PROPS,
-        functionRef: BindingTypes.PROPS,
-        objectRef: BindingTypes.PROPS,
-        dateTime: BindingTypes.PROPS,
-        array: BindingTypes.PROPS,
-        arrayRef: BindingTypes.PROPS,
-        tuple: BindingTypes.PROPS,
-        set: BindingTypes.PROPS,
-        literal: BindingTypes.PROPS,
-        optional: BindingTypes.PROPS,
-        recordRef: BindingTypes.PROPS,
-        interface: BindingTypes.PROPS,
-        alias: BindingTypes.PROPS,
-        method: BindingTypes.PROPS,
-        symbol: BindingTypes.PROPS,
-        objectOrFn: BindingTypes.PROPS,
-        extract: BindingTypes.PROPS,
-        exclude: BindingTypes.PROPS,
-        union: BindingTypes.PROPS,
-        literalUnion: BindingTypes.PROPS,
-        literalUnionNumber: BindingTypes.PROPS,
-        literalUnionMixed: BindingTypes.PROPS,
-        intersection: BindingTypes.PROPS,
-        intersection2: BindingTypes.PROPS,
-        foo: BindingTypes.PROPS,
-        uppercase: BindingTypes.PROPS,
-        params: BindingTypes.PROPS,
-        nonNull: BindingTypes.PROPS,
-        unknown: BindingTypes.PROPS,
-        unknownUnion: BindingTypes.PROPS,
-        unknownIntersection: BindingTypes.PROPS,
-        unknownUnionWithBoolean: BindingTypes.PROPS,
-        unknownUnionWithFunction: BindingTypes.PROPS
-      })
-    })
-
-    test('defineProps w/ interface', () => {
-      const { content, bindings } = compile(`
-      <script setup lang="ts">
-      interface Props { x?: number }
-      defineProps<Props>()
-      </script>
-      `)
-      assertCode(content)
-      expect(content).toMatch(`x: { type: Number, required: false }`)
-      expect(bindings).toStrictEqual({
-        x: BindingTypes.PROPS
-      })
-    })
-
-    test('defineProps w/ extends interface', () => {
-      const { content, bindings } = compile(`
-      <script lang="ts">
-        interface Foo { x?: number }
-      </script>
-      <script setup lang="ts">
-        interface Bar extends Foo { y?: number }
-        interface Props extends Bar {
-          z: number
-          y: string
-        }
-        defineProps<Props>()
-      </script>
-      `)
-      assertCode(content)
-      expect(content).toMatch(`z: { type: Number, required: true }`)
-      expect(content).toMatch(`y: { type: String, required: true }`)
-      expect(content).toMatch(`x: { type: Number, required: false }`)
-      expect(bindings).toStrictEqual({
-        x: BindingTypes.PROPS,
-        y: BindingTypes.PROPS,
-        z: BindingTypes.PROPS
-      })
-    })
-
-    test('defineProps w/ exported interface', () => {
-      const { content, bindings } = compile(`
-      <script setup lang="ts">
-      export interface Props { x?: number }
-      defineProps<Props>()
-      </script>
-      `)
-      assertCode(content)
-      expect(content).toMatch(`x: { type: Number, required: false }`)
-      expect(bindings).toStrictEqual({
-        x: BindingTypes.PROPS
-      })
-    })
-
-    test('defineProps w/ exported interface in normal script', () => {
-      const { content, bindings } = compile(`
-      <script lang="ts">
-        export interface Props { x?: number }
-      </script>
-      <script setup lang="ts">
-        defineProps<Props>()
-      </script>
-      `)
-      assertCode(content)
-      expect(content).toMatch(`x: { type: Number, required: false }`)
-      expect(bindings).toStrictEqual({
-        x: BindingTypes.PROPS
-      })
-    })
-
-    test('defineProps w/ type alias', () => {
-      const { content, bindings } = compile(`
-      <script setup lang="ts">
-      type Props = { x?: number }
-      defineProps<Props>()
-      </script>
-      `)
-      assertCode(content)
-      expect(content).toMatch(`x: { type: Number, required: false }`)
-      expect(bindings).toStrictEqual({
-        x: BindingTypes.PROPS
-      })
-    })
-
-    test('defineProps w/ exported type alias', () => {
-      const { content, bindings } = compile(`
-      <script setup lang="ts">
-      export type Props = { x?: number }
-      defineProps<Props>()
-      </script>
-      `)
-      assertCode(content)
-      expect(content).toMatch(`x: { type: Number, required: false }`)
-      expect(bindings).toStrictEqual({
-        x: BindingTypes.PROPS
-      })
-    })
-
-    test('defineProps w/ TS assertion', () => {
-      const { content, bindings } = compile(`
-      <script setup lang="ts">
-        defineProps(['foo'])! as any
-      </script>
-    `)
-      expect(content).toMatch(`props: ['foo']`)
-      assertCode(content)
-      expect(bindings).toStrictEqual({
-        foo: BindingTypes.PROPS
-      })
-    })
-
-    test('withDefaults (static)', () => {
-      const { content, bindings } = compile(`
-      <script setup lang="ts">
-      const props = withDefaults(defineProps<{
-        foo?: string
-        bar?: number;
-        baz: boolean;
-        qux?(): number;
-        quux?(): void
-        quuxx?: Promise<string>;
-        fred?: string
-      }>(), {
-        foo: 'hi',
-        qux() { return 1 },
-        ['quux']() { },
-        async quuxx() { return await Promise.resolve('hi') },
-        get fred() { return 'fred' }
-      })
-      </script>
-      `)
-      assertCode(content)
-      expect(content).toMatch(
-        `foo: { type: String, required: false, default: 'hi' }`
-      )
-      expect(content).toMatch(`bar: { type: Number, required: false }`)
-      expect(content).toMatch(`baz: { type: Boolean, required: true }`)
-      expect(content).toMatch(
-        `qux: { type: Function, required: false, default() { return 1 } }`
-      )
-      expect(content).toMatch(
-        `quux: { type: Function, required: false, default() { } }`
-      )
-      expect(content).toMatch(
-        `quuxx: { type: Promise, required: false, async default() { return await Promise.resolve('hi') } }`
-      )
-      expect(content).toMatch(
-        `fred: { type: String, required: false, get default() { return 'fred' } }`
-      )
-      expect(content).toMatch(`const props = __props`)
-      expect(bindings).toStrictEqual({
-        foo: BindingTypes.PROPS,
-        bar: BindingTypes.PROPS,
-        baz: BindingTypes.PROPS,
-        qux: BindingTypes.PROPS,
-        quux: BindingTypes.PROPS,
-        quuxx: BindingTypes.PROPS,
-        fred: BindingTypes.PROPS,
-        props: BindingTypes.SETUP_CONST
-      })
-    })
-
-    test('withDefaults (static) + normal script', () => {
-      const { content } = compile(`
-      <script lang="ts">
-        interface Props {
-          a?: string;
-        }
-      </script>
-      <script setup lang="ts">
-        const props = withDefaults(defineProps<Props>(), {
-          a: "a",
-        });
-      </script>
-      `)
-      assertCode(content)
-    })
-
-    // #7111
-    test('withDefaults (static) w/ production mode', () => {
-      const { content } = compile(
-        `
-      <script setup lang="ts">
-      const props = withDefaults(defineProps<{
-        foo: () => void
-        bar: boolean
-        baz: boolean | (() => void)
-        qux: string | number
-      }>(), {
-        baz: true,
-        qux: 'hi'
-      })
-      </script>
-      `,
-        { isProd: true }
-      )
-      assertCode(content)
-      expect(content).toMatch(`const props = __props`)
-
-      // foo has no default value, the Function can be dropped
-      expect(content).toMatch(`foo: {}`)
-      expect(content).toMatch(`bar: { type: Boolean }`)
-      expect(content).toMatch(
-        `baz: { type: [Boolean, Function], default: true }`
-      )
-      expect(content).toMatch(`qux: { default: 'hi' }`)
-    })
-
-    test('withDefaults (dynamic)', () => {
-      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()
-      )
-    })
-
-    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
-    test('withDefaults (dynamic) w/ production mode', () => {
-      const { content } = compile(
-        `
-      <script setup lang="ts">
-      import { defaults } from './foo'
-      const props = withDefaults(defineProps<{
-        foo: () => void
-        bar: boolean
-        baz: boolean | (() => void)
-        qux: string | number
-      }>(), { ...defaults })
-      </script>
-      `,
-        { isProd: true }
-      )
-      assertCode(content)
-      expect(content).toMatch(`import { mergeDefaults as _mergeDefaults`)
-      expect(content).toMatch(
-        `
-  _mergeDefaults({
-    foo: { type: Function },
-    bar: { type: Boolean },
-    baz: { type: [Boolean, Function] },
-    qux: {}
-  }, { ...defaults })`.trim()
-      )
-    })
-
-    test('withDefaults w/ dynamic object method', () => {
-      const { content } = compile(`
-      <script setup lang="ts">
-      const props = withDefaults(defineProps<{
-        foo?: () => 'string'
-      }>(), {
-        ['fo' + 'o']() { return 'foo' }
-      })
-      </script>
-      `)
-      assertCode(content)
-      expect(content).toMatch(`import { mergeDefaults as _mergeDefaults`)
-      expect(content).toMatch(
-        `
-  _mergeDefaults({
-    foo: { type: Function, required: false }
-  }, {
-        ['fo' + 'o']() { return 'foo' }
-      })`.trim()
-      )
-    })
-
-    test('defineEmits w/ type', () => {
-      const { content } = compile(`
-      <script setup lang="ts">
-      const emit = defineEmits<(e: 'foo' | 'bar') => void>()
-      </script>
-      `)
-      assertCode(content)
-      expect(content).toMatch(`emits: ["foo", "bar"]`)
-    })
-
-    test('defineEmits w/ type (union)', () => {
-      const type = `((e: 'foo' | 'bar') => void) | ((e: 'baz', id: number) => void)`
-      expect(() =>
-        compile(`
-      <script setup lang="ts">
-      const emit = defineEmits<${type}>()
-      </script>
-      `)
-      ).toThrow()
-    })
-
-    test('defineEmits w/ type (type literal w/ call signatures)', () => {
-      const type = `{(e: 'foo' | 'bar'): void; (e: 'baz', id: number): void;}`
-      const { content } = compile(`
-      <script setup lang="ts">
-      const emit = defineEmits<${type}>()
-      </script>
-      `)
-      assertCode(content)
-      expect(content).toMatch(`emits: ["foo", "bar", "baz"]`)
-    })
-
-    test('defineEmits w/ type (interface)', () => {
-      const { content } = compile(`
-      <script setup lang="ts">
-      interface Emits { (e: 'foo' | 'bar'): void }
-      const emit = defineEmits<Emits>()
-      </script>
-      `)
-      assertCode(content)
-      expect(content).toMatch(`emits: ["foo", "bar"]`)
-    })
-
-    test('defineEmits w/ type (exported interface)', () => {
-      const { content } = compile(`
-      <script setup lang="ts">
-      export interface Emits { (e: 'foo' | 'bar'): void }
-      const emit = defineEmits<Emits>()
-      </script>
-      `)
-      assertCode(content)
-      expect(content).toMatch(`emits: ["foo", "bar"]`)
-    })
-
-    test('defineEmits w/ type from normal script', () => {
-      const { content } = compile(`
-      <script lang="ts">
-        export interface Emits { (e: 'foo' | 'bar'): void }
-      </script>
-      <script setup lang="ts">
-      const emit = defineEmits<Emits>()
-      </script>
-      `)
-      assertCode(content)
-      expect(content).toMatch(`emits: ["foo", "bar"]`)
-    })
-
-    test('defineEmits w/ type (type alias)', () => {
-      const { content } = compile(`
-      <script setup lang="ts">
-      type Emits = { (e: 'foo' | 'bar'): void }
-      const emit = defineEmits<Emits>()
-      </script>
-      `)
-      assertCode(content)
-      expect(content).toMatch(`emits: ["foo", "bar"]`)
-    })
-
-    test('defineEmits w/ type (exported type alias)', () => {
-      const { content } = compile(`
-      <script setup lang="ts">
-      export type Emits = { (e: 'foo' | 'bar'): void }
-      const emit = defineEmits<Emits>()
-      </script>
-      `)
-      assertCode(content)
-      expect(content).toMatch(`emits: ["foo", "bar"]`)
-    })
-
-    test('defineEmits w/ type (referenced function type)', () => {
-      const { content } = compile(`
-      <script setup lang="ts">
-      type Emits = (e: 'foo' | 'bar') => void
-      const emit = defineEmits<Emits>()
-      </script>
-      `)
-      assertCode(content)
-      expect(content).toMatch(`emits: ["foo", "bar"]`)
-    })
-
-    test('defineEmits w/ type (referenced exported function type)', () => {
-      const { content } = compile(`
-      <script setup lang="ts">
-      export type Emits = (e: 'foo' | 'bar') => void
-      const emit = defineEmits<Emits>()
-      </script>
-      `)
-      assertCode(content)
-      expect(content).toMatch(`emits: ["foo", "bar"]`)
-    })
-
-    // #5393
-    test('defineEmits w/ type (interface ts type)', () => {
-      const { content } = compile(`
-      <script setup lang="ts">
-      interface Emits { (e: 'foo'): void }
-      const emit: Emits = defineEmits(['foo'])
-      </script>
-      `)
-      assertCode(content)
-      expect(content).toMatch(`emits: ['foo']`)
-    })
-
-    test('defineEmits w/ type (property syntax)', () => {
-      const { content } = compile(`
-      <script setup lang="ts">
-      const emit = defineEmits<{ foo: [], bar: [] }>()
-      </script>
-      `)
-      expect(content).toMatch(`emits: ["foo", "bar"]`)
-      assertCode(content)
-    })
-
-    // #8040
-    test('defineEmits w/ type (property syntax string literal)', () => {
-      const { content } = compile(`
-      <script setup lang="ts">
-      const emit = defineEmits<{ 'foo:bar': [] }>()
-      </script>
-      `)
-      expect(content).toMatch(`emits: ["foo:bar"]`)
-      assertCode(content)
-    })
-
-    describe('defineSlots()', () => {
-      test('basic usage', () => {
-        const { content } = compile(`
-          <script setup lang="ts">
-          const slots = defineSlots<{
-            default: { msg: string }
-          }>()
-          </script>
-        `)
-        assertCode(content)
-        expect(content).toMatch(`const slots = _useSlots()`)
-        expect(content).not.toMatch('defineSlots')
-      })
-
-      test('w/o return value', () => {
-        const { content } = compile(`
-          <script setup lang="ts">
-          defineSlots<{
-            default: { msg: string }
-          }>()
-          </script>
-        `)
-        assertCode(content)
-        expect(content).not.toMatch('defineSlots')
-        expect(content).not.toMatch(`_useSlots`)
-      })
-
-      test('w/o generic params', () => {
-        const { content } = compile(`
-          <script setup>
-          const slots = defineSlots()
-          </script>
-        `)
-        assertCode(content)
-        expect(content).toMatch(`const slots = _useSlots()`)
-        expect(content).not.toMatch('defineSlots')
-      })
-    })
-
-    describe('defineModel()', () => {
-      test('basic usage', () => {
-        const { content, bindings } = compile(
-          `
-          <script setup lang="ts">
-          const modelValue = defineModel<boolean | string>()
-          const count = defineModel<number>('count')
-          const disabled = defineModel<number>('disabled', { required: false })
-          const any = defineModel<any | boolean>('any')
-          </script>
-          `,
-          { defineModel: true }
-        )
-        assertCode(content)
-        expect(content).toMatch('"modelValue": { type: [Boolean, String] }')
-        expect(content).toMatch('"count": { type: Number }')
-        expect(content).toMatch(
-          '"disabled": { type: Number, ...{ required: false } }'
-        )
-        expect(content).toMatch('"any": { type: Boolean, skipCheck: true }')
-        expect(content).toMatch(
-          'emits: ["update:modelValue", "update:count", "update:disabled", "update:any"]'
-        )
-
-        expect(content).toMatch(
-          `const modelValue = _useModel(__props, "modelValue")`
-        )
-        expect(content).toMatch(`const count = _useModel(__props, "count")`)
-        expect(content).toMatch(
-          `const disabled = _useModel(__props, "disabled")`
-        )
-        expect(content).toMatch(`const any = _useModel(__props, "any")`)
-
-        expect(bindings).toStrictEqual({
-          modelValue: BindingTypes.SETUP_REF,
-          count: BindingTypes.SETUP_REF,
-          disabled: BindingTypes.SETUP_REF,
-          any: BindingTypes.SETUP_REF
-        })
-      })
-
-      test('w/ production mode', () => {
-        const { content, bindings } = compile(
-          `
-          <script setup lang="ts">
-          const modelValue = defineModel<boolean>()
-          const fn = defineModel<() => void>('fn')
-          const fnWithDefault = defineModel<() => void>('fnWithDefault', { default: () => null })
-          const str = defineModel<string>('str')
-          const optional = defineModel<string>('optional', { required: false })
-          </script>
-          `,
-          { defineModel: true, isProd: true }
-        )
-        assertCode(content)
-        expect(content).toMatch('"modelValue": { type: Boolean }')
-        expect(content).toMatch('"fn": {}')
-        expect(content).toMatch(
-          '"fnWithDefault": { type: Function, ...{ default: () => null } },'
-        )
-        expect(content).toMatch('"str": {}')
-        expect(content).toMatch('"optional": { required: false }')
-        expect(content).toMatch(
-          'emits: ["update:modelValue", "update:fn", "update:fnWithDefault", "update:str", "update:optional"]'
-        )
-        expect(content).toMatch(
-          `const modelValue = _useModel(__props, "modelValue")`
-        )
-        expect(content).toMatch(`const fn = _useModel(__props, "fn")`)
-        expect(content).toMatch(`const str = _useModel(__props, "str")`)
-        expect(bindings).toStrictEqual({
-          modelValue: BindingTypes.SETUP_REF,
-          fn: BindingTypes.SETUP_REF,
-          fnWithDefault: BindingTypes.SETUP_REF,
-          str: BindingTypes.SETUP_REF,
-          optional: BindingTypes.SETUP_REF
-        })
-      })
-    })
-
     test('runtime Enum', () => {
       const { content, bindings } = compile(
         `<script setup lang="ts">
@@ -1946,56 +861,6 @@ const emit = defineEmits(['a', 'b'])
       })
     })
 
-    test('runtime inference for Enum in defineProps', () => {
-      expect(
-        compile(
-          `<script setup lang="ts">
-        const enum Foo { A = 123 }
-        defineProps<{
-          foo: Foo
-        }>()
-        </script>`,
-          { hoistStatic: true }
-        ).content
-      ).toMatch(`foo: { type: Number`)
-
-      expect(
-        compile(
-          `<script setup lang="ts">
-        const enum Foo { A = '123' }
-        defineProps<{
-          foo: Foo
-        }>()
-        </script>`,
-          { hoistStatic: true }
-        ).content
-      ).toMatch(`foo: { type: String`)
-
-      expect(
-        compile(
-          `<script setup lang="ts">
-        const enum Foo { A = '123', B = 123 }
-        defineProps<{
-          foo: Foo
-        }>()
-        </script>`,
-          { hoistStatic: true }
-        ).content
-      ).toMatch(`foo: { type: [String, Number]`)
-
-      expect(
-        compile(
-          `<script setup lang="ts">
-        const enum Foo { A, B }
-        defineProps<{
-          foo: Foo
-        }>()
-        </script>`,
-          { hoistStatic: true }
-        ).content
-      ).toMatch(`foo: { type: Number`)
-    })
-
     test('import type', () => {
       const { content } = compile(
         `<script setup lang="ts">
@@ -2154,20 +1019,6 @@ const emit = defineEmits(['a', 'b'])
       ).toThrow(moduleErrorMsg)
     })
 
-    test('defineProps/Emit() w/ both type and non-type args', () => {
-      expect(() => {
-        compile(`<script setup lang="ts">
-        defineProps<{}>({})
-        </script>`)
-      }).toThrow(`cannot accept both type and non-type arguments`)
-
-      expect(() => {
-        compile(`<script setup lang="ts">
-        defineEmits<{}>({})
-        </script>`)
-      }).toThrow(`cannot accept both type and non-type arguments`)
-    })
-
     test('defineProps/Emit() referencing local var', () => {
       expect(() =>
         compile(`<script setup>
@@ -2232,19 +1083,6 @@ const emit = defineEmits(['a', 'b'])
         </script>`).content
       )
     })
-
-    test('mixed usage of property / 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.`
-      )
-    })
   })
 })
 
diff --git a/packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineEmits.spec.ts.snap b/packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineEmits.spec.ts.snap
new file mode 100644 (file)
index 0000000..5add78a
--- /dev/null
@@ -0,0 +1,232 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`defineEmits > basic usage 1`] = `
+"export default {
+  emits: ['foo', 'bar'],
+  setup(__props, { expose: __expose, emit: myEmit }) {
+  __expose();
+
+
+
+return { myEmit }
+}
+
+}"
+`;
+
+exports[`defineEmits > w/ runtime options 1`] = `
+"import { defineComponent as _defineComponent } from 'vue'
+
+export default /*#__PURE__*/_defineComponent({
+  emits: ['a', 'b'],
+  setup(__props, { expose: __expose, emit }) {
+  __expose();
+
+
+
+return { emit }
+}
+
+})"
+`;
+
+exports[`defineEmits > w/ type (exported interface) 1`] = `
+"import { defineComponent as _defineComponent } from 'vue'
+export interface Emits { (e: 'foo' | 'bar'): void }
+    
+export default /*#__PURE__*/_defineComponent({
+  emits: [\\"foo\\", \\"bar\\"],
+  setup(__props, { expose: __expose, emit }) {
+  __expose();
+
+    
+    
+return { emit }
+}
+
+})"
+`;
+
+exports[`defineEmits > w/ type (exported type alias) 1`] = `
+"import { defineComponent as _defineComponent } from 'vue'
+export type Emits = { (e: 'foo' | 'bar'): void }
+    
+export default /*#__PURE__*/_defineComponent({
+  emits: [\\"foo\\", \\"bar\\"],
+  setup(__props, { expose: __expose, emit }) {
+  __expose();
+
+    
+    
+return { emit }
+}
+
+})"
+`;
+
+exports[`defineEmits > w/ type (interface ts type) 1`] = `
+"import { defineComponent as _defineComponent } from 'vue'
+interface Emits { (e: 'foo'): void }
+    
+export default /*#__PURE__*/_defineComponent({
+  emits: ['foo'],
+  setup(__props, { expose: __expose, emit }) {
+  __expose();
+
+    
+    
+return { emit }
+}
+
+})"
+`;
+
+exports[`defineEmits > w/ type (interface) 1`] = `
+"import { defineComponent as _defineComponent } from 'vue'
+interface Emits { (e: 'foo' | 'bar'): void }
+    
+export default /*#__PURE__*/_defineComponent({
+  emits: [\\"foo\\", \\"bar\\"],
+  setup(__props, { expose: __expose, emit }) {
+  __expose();
+
+    
+    
+return { emit }
+}
+
+})"
+`;
+
+exports[`defineEmits > w/ type (property syntax string literal) 1`] = `
+"import { defineComponent as _defineComponent } from 'vue'
+
+export default /*#__PURE__*/_defineComponent({
+  emits: [\\"foo:bar\\"],
+  setup(__props, { expose: __expose, emit }) {
+  __expose();
+
+    
+    
+return { emit }
+}
+
+})"
+`;
+
+exports[`defineEmits > w/ type (property syntax) 1`] = `
+"import { defineComponent as _defineComponent } from 'vue'
+
+export default /*#__PURE__*/_defineComponent({
+  emits: [\\"foo\\", \\"bar\\"],
+  setup(__props, { expose: __expose, emit }) {
+  __expose();
+
+    
+    
+return { emit }
+}
+
+})"
+`;
+
+exports[`defineEmits > w/ type (referenced exported function type) 1`] = `
+"import { defineComponent as _defineComponent } from 'vue'
+export type Emits = (e: 'foo' | 'bar') => void
+    
+export default /*#__PURE__*/_defineComponent({
+  emits: [\\"foo\\", \\"bar\\"],
+  setup(__props, { expose: __expose, emit }) {
+  __expose();
+
+    
+    
+return { emit }
+}
+
+})"
+`;
+
+exports[`defineEmits > w/ type (referenced function type) 1`] = `
+"import { defineComponent as _defineComponent } from 'vue'
+type Emits = (e: 'foo' | 'bar') => void
+    
+export default /*#__PURE__*/_defineComponent({
+  emits: [\\"foo\\", \\"bar\\"],
+  setup(__props, { expose: __expose, emit }) {
+  __expose();
+
+    
+    
+return { emit }
+}
+
+})"
+`;
+
+exports[`defineEmits > w/ type (type alias) 1`] = `
+"import { defineComponent as _defineComponent } from 'vue'
+type Emits = { (e: 'foo' | 'bar'): void }
+    
+export default /*#__PURE__*/_defineComponent({
+  emits: [\\"foo\\", \\"bar\\"],
+  setup(__props, { expose: __expose, emit }) {
+  __expose();
+
+    
+    
+return { emit }
+}
+
+})"
+`;
+
+exports[`defineEmits > w/ type (type literal w/ call signatures) 1`] = `
+"import { defineComponent as _defineComponent } from 'vue'
+
+export default /*#__PURE__*/_defineComponent({
+  emits: [\\"foo\\", \\"bar\\", \\"baz\\"],
+  setup(__props, { expose: __expose, emit }) {
+  __expose();
+
+    
+    
+return { emit }
+}
+
+})"
+`;
+
+exports[`defineEmits > w/ type 1`] = `
+"import { defineComponent as _defineComponent } from 'vue'
+
+export default /*#__PURE__*/_defineComponent({
+  emits: [\\"foo\\", \\"bar\\"],
+  setup(__props, { expose: __expose, emit }) {
+  __expose();
+
+    
+    
+return { emit }
+}
+
+})"
+`;
+
+exports[`defineEmits > w/ type from normal script 1`] = `
+"import { defineComponent as _defineComponent } from 'vue'
+
+      export interface Emits { (e: 'foo' | 'bar'): void }
+    
+export default /*#__PURE__*/_defineComponent({
+  emits: [\\"foo\\", \\"bar\\"],
+  setup(__props, { expose: __expose, emit }) {
+  __expose();
+
+    
+    
+return { emit }
+}
+
+})"
+`;
diff --git a/packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineExpose.spec.ts.snap b/packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineExpose.spec.ts.snap
new file mode 100644 (file)
index 0000000..d727264
--- /dev/null
@@ -0,0 +1,28 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`<script> after <script setup> the script content not end with \`\\n\` 1`] = `
+"import { x } from './x'
+  const n = 1
+
+export default {
+  setup(__props, { expose: __expose }) {
+  __expose();
+
+  
+return { n, get x() { return x } }
+}
+
+}"
+`;
+
+exports[`defineExpose() 1`] = `
+"export default {
+  setup(__props, { expose: __expose }) {
+
+__expose({ foo: 123 })
+
+return {  }
+}
+
+}"
+`;
diff --git a/packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineModel.spec.ts.snap b/packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineModel.spec.ts.snap
new file mode 100644 (file)
index 0000000..fdfd371
--- /dev/null
@@ -0,0 +1,147 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`defineModel() > basic usage 1`] = `
+"import { useModel as _useModel } from 'vue'
+
+export default {
+  props: {
+    \\"modelValue\\": { required: true },
+    \\"count\\": {},
+  },
+  emits: [\\"update:modelValue\\", \\"update:count\\"],
+  setup(__props, { expose: __expose }) {
+  __expose();
+
+      const modelValue = _useModel(__props, \\"modelValue\\")
+      const c = _useModel(__props, \\"count\\")
+      
+return { modelValue, c }
+}
+
+}"
+`;
+
+exports[`defineModel() > w/ array props 1`] = `
+"import { useModel as _useModel, mergeModels as _mergeModels } from 'vue'
+
+export default {
+  props: _mergeModels(['foo', 'bar'], {
+    \\"count\\": {},
+  }),
+  emits: [\\"update:count\\"],
+  setup(__props, { expose: __expose }) {
+  __expose();
+
+      
+      const count = _useModel(__props, \\"count\\")
+      
+return { count }
+}
+
+}"
+`;
+
+exports[`defineModel() > w/ defineProps and defineEmits 1`] = `
+"import { useModel as _useModel, mergeModels as _mergeModels } from 'vue'
+
+export default {
+  props: _mergeModels({ foo: String }, {
+    \\"modelValue\\": { default: 0 },
+  }),
+  emits: _mergeModels(['change'], [\\"update:modelValue\\"]),
+  setup(__props, { expose: __expose }) {
+  __expose();
+
+      
+      
+      const count = _useModel(__props, \\"modelValue\\")
+      
+return { count }
+}
+
+}"
+`;
+
+exports[`defineModel() > w/ local flag 1`] = `
+"import { useModel as _useModel } from 'vue'
+const local = true
+      
+export default {
+  props: {
+    \\"modelValue\\": { local: true, default: 1 },
+    \\"bar\\": { [key]: true },
+    \\"baz\\": { ...x },
+    \\"qux\\": x,
+    \\"foo2\\": { local: true, ...x },
+    \\"hoist\\": { local },
+  },
+  emits: [\\"update:modelValue\\", \\"update:bar\\", \\"update:baz\\", \\"update:qux\\", \\"update:foo2\\", \\"update:hoist\\"],
+  setup(__props, { expose: __expose }) {
+  __expose();
+
+      const foo = _useModel(__props, \\"modelValue\\", { local: true })
+      const bar = _useModel(__props, \\"bar\\", { [key]: true })
+      const baz = _useModel(__props, \\"baz\\", { ...x })
+      const qux = _useModel(__props, \\"qux\\", x)
+
+      const foo2 = _useModel(__props, \\"foo2\\", { local: true })
+
+      const hoist = _useModel(__props, \\"hoist\\", { local })
+      
+return { foo, bar, baz, qux, foo2, local, hoist }
+}
+
+}"
+`;
+
+exports[`defineModel() > w/ types, basic usage 1`] = `
+"import { useModel as _useModel, defineComponent as _defineComponent } from 'vue'
+
+export default /*#__PURE__*/_defineComponent({
+  props: {
+    \\"modelValue\\": { type: [Boolean, String] },
+    \\"count\\": { type: Number },
+    \\"disabled\\": { type: Number, ...{ required: false } },
+    \\"any\\": { type: Boolean, skipCheck: true },
+  },
+  emits: [\\"update:modelValue\\", \\"update:count\\", \\"update:disabled\\", \\"update:any\\"],
+  setup(__props, { expose: __expose }) {
+  __expose();
+
+      const modelValue = _useModel(__props, \\"modelValue\\")
+      const count = _useModel(__props, \\"count\\")
+      const disabled = _useModel(__props, \\"disabled\\")
+      const any = _useModel(__props, \\"any\\")
+      
+return { modelValue, count, disabled, any }
+}
+
+})"
+`;
+
+exports[`defineModel() > w/ types, production mode 1`] = `
+"import { useModel as _useModel, defineComponent as _defineComponent } from 'vue'
+
+export default /*#__PURE__*/_defineComponent({
+  props: {
+    \\"modelValue\\": { type: Boolean },
+    \\"fn\\": {},
+    \\"fnWithDefault\\": { type: Function, ...{ default: () => null } },
+    \\"str\\": {},
+    \\"optional\\": { required: false },
+  },
+  emits: [\\"update:modelValue\\", \\"update:fn\\", \\"update:fnWithDefault\\", \\"update:str\\", \\"update:optional\\"],
+  setup(__props, { expose: __expose }) {
+  __expose();
+
+      const modelValue = _useModel(__props, \\"modelValue\\")
+      const fn = _useModel(__props, \\"fn\\")
+      const fnWithDefault = _useModel(__props, \\"fnWithDefault\\")
+      const str = _useModel(__props, \\"str\\")
+      const optional = _useModel(__props, \\"optional\\")
+      
+return { modelValue, fn, fnWithDefault, str, optional }
+}
+
+})"
+`;
diff --git a/packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineOptions.spec.ts.snap b/packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineOptions.spec.ts.snap
new file mode 100644 (file)
index 0000000..47f3cef
--- /dev/null
@@ -0,0 +1,27 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`defineOptions() > basic usage 1`] = `
+"export default /*#__PURE__*/Object.assign({ name: 'FooApp' }, {
+  setup(__props, { expose: __expose }) {
+  __expose();
+
+      
+      
+return {  }
+}
+
+})"
+`;
+
+exports[`defineOptions() > empty argument 1`] = `
+"export default {
+  setup(__props, { expose: __expose }) {
+  __expose();
+
+      
+      
+return {  }
+}
+
+}"
+`;
diff --git a/packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineProps.spec.ts.snap b/packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineProps.spec.ts.snap
new file mode 100644 (file)
index 0000000..4732844
--- /dev/null
@@ -0,0 +1,437 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`defineProps > basic usage 1`] = `
+"const bar = 1
+
+export default {
+  props: {
+  foo: String
+},
+  setup(__props, { expose: __expose }) {
+  __expose();
+
+const props = __props;
+
+
+
+return { props, bar }
+}
+
+}"
+`;
+
+exports[`defineProps > defineProps w/ runtime options 1`] = `
+"import { defineComponent as _defineComponent } from 'vue'
+
+export default /*#__PURE__*/_defineComponent({
+  props: { foo: String },
+  setup(__props, { expose: __expose }) {
+  __expose();
+
+const props = __props;
+
+
+
+return { props }
+}
+
+})"
+`;
+
+exports[`defineProps > w/ TS assertion 1`] = `
+"import { defineComponent as _defineComponent } from 'vue'
+
+export default /*#__PURE__*/_defineComponent({
+  props: ['foo'],
+  setup(__props, { expose: __expose }) {
+  __expose();
+
+      
+    
+return {  }
+}
+
+})"
+`;
+
+exports[`defineProps > w/ exported interface 1`] = `
+"import { defineComponent as _defineComponent } from 'vue'
+export interface Props { x?: number }
+    
+export default /*#__PURE__*/_defineComponent({
+  props: {
+    x: { type: Number, required: false }
+  },
+  setup(__props: any, { expose: __expose }) {
+  __expose();
+
+    
+    
+return {  }
+}
+
+})"
+`;
+
+exports[`defineProps > w/ exported interface in normal script 1`] = `
+"import { defineComponent as _defineComponent } from 'vue'
+
+      export interface Props { x?: number }
+    
+export default /*#__PURE__*/_defineComponent({
+  props: {
+    x: { type: Number, required: false }
+  },
+  setup(__props: any, { expose: __expose }) {
+  __expose();
+
+      
+    
+return {  }
+}
+
+})"
+`;
+
+exports[`defineProps > w/ exported type alias 1`] = `
+"import { defineComponent as _defineComponent } from 'vue'
+export type Props = { x?: number }
+    
+export default /*#__PURE__*/_defineComponent({
+  props: {
+    x: { type: Number, required: false }
+  },
+  setup(__props: any, { expose: __expose }) {
+  __expose();
+
+    
+    
+return {  }
+}
+
+})"
+`;
+
+exports[`defineProps > w/ extends interface 1`] = `
+"import { defineComponent as _defineComponent } from 'vue'
+interface Bar extends Foo { y?: number }
+      interface Props extends Bar {
+        z: number
+        y: string
+      }
+      
+      interface Foo { x?: number }
+    
+export default /*#__PURE__*/_defineComponent({
+  props: {
+    z: { type: Number, required: true },
+    y: { type: String, required: true },
+    x: { type: Number, required: false }
+  },
+  setup(__props: any, { expose: __expose }) {
+  __expose();
+
+      
+    
+return {  }
+}
+
+})"
+`;
+
+exports[`defineProps > w/ external definition 1`] = `
+"import { propsModel } from './props'
+    
+export default {
+  props: propsModel,
+  setup(__props, { expose: __expose }) {
+  __expose();
+
+const props = __props;
+
+    
+    
+return { props, get propsModel() { return propsModel } }
+}
+
+}"
+`;
+
+exports[`defineProps > w/ interface 1`] = `
+"import { defineComponent as _defineComponent } from 'vue'
+interface Props { x?: number }
+    
+export default /*#__PURE__*/_defineComponent({
+  props: {
+    x: { type: Number, required: false }
+  },
+  setup(__props: any, { expose: __expose }) {
+  __expose();
+
+    
+    
+return {  }
+}
+
+})"
+`;
+
+exports[`defineProps > w/ leading code 1`] = `
+"import { x } from './x'
+    
+export default {
+  props: {},
+  setup(__props, { expose: __expose }) {
+  __expose();
+
+const props = __props;
+
+    
+return { props, get x() { return x } }
+}
+
+}"
+`;
+
+exports[`defineProps > w/ type 1`] = `
+"import { defineComponent as _defineComponent } from 'vue'
+interface Test {}
+
+    type Alias = number[]
+
+    
+export default /*#__PURE__*/_defineComponent({
+  props: {
+    string: { type: String, required: true },
+    number: { type: Number, required: true },
+    boolean: { type: Boolean, required: true },
+    object: { type: Object, required: true },
+    objectLiteral: { type: Object, required: true },
+    fn: { type: Function, required: true },
+    functionRef: { type: Function, required: true },
+    objectRef: { type: Object, required: true },
+    dateTime: { type: Date, required: true },
+    array: { type: Array, required: true },
+    arrayRef: { type: Array, required: true },
+    tuple: { type: Array, required: true },
+    set: { type: Set, required: true },
+    literal: { type: String, required: true },
+    optional: { type: null, required: false },
+    recordRef: { type: Object, required: true },
+    interface: { type: Object, required: true },
+    alias: { type: Array, required: true },
+    method: { type: Function, required: true },
+    symbol: { type: Symbol, required: true },
+    extract: { type: Number, required: true },
+    exclude: { type: [Number, Boolean], required: true },
+    uppercase: { type: String, required: true },
+    params: { type: Array, required: true },
+    nonNull: { type: String, required: true },
+    objectOrFn: { type: [Function, Object], required: true },
+    union: { type: [String, Number], required: true },
+    literalUnion: { type: String, required: true },
+    literalUnionNumber: { type: Number, required: true },
+    literalUnionMixed: { type: [String, Number, Boolean], required: true },
+    intersection: { type: Object, required: true },
+    intersection2: { type: String, required: true },
+    foo: { type: [Function, null], required: true },
+    unknown: { type: null, required: true },
+    unknownUnion: { type: null, required: true },
+    unknownIntersection: { type: Object, required: true },
+    unknownUnionWithBoolean: { type: Boolean, required: true, skipCheck: true },
+    unknownUnionWithFunction: { type: Function, required: true, skipCheck: true }
+  },
+  setup(__props: any, { expose: __expose }) {
+  __expose();
+
+    
+    
+return {  }
+}
+
+})"
+`;
+
+exports[`defineProps > w/ type alias 1`] = `
+"import { defineComponent as _defineComponent } from 'vue'
+type Props = { x?: number }
+    
+export default /*#__PURE__*/_defineComponent({
+  props: {
+    x: { type: Number, required: false }
+  },
+  setup(__props: any, { expose: __expose }) {
+  __expose();
+
+    
+    
+return {  }
+}
+
+})"
+`;
+
+exports[`defineProps > withDefaults (dynamic) 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;
+
+    
+    
+return { props, get defaults() { return defaults } }
+}
+
+})"
+`;
+
+exports[`defineProps > withDefaults (dynamic) w/ production mode 1`] = `
+"import { mergeDefaults as _mergeDefaults, defineComponent as _defineComponent } from 'vue'
+import { defaults } from './foo'
+    
+export default /*#__PURE__*/_defineComponent({
+  props: _mergeDefaults({
+    foo: { type: Function },
+    bar: { type: Boolean },
+    baz: { type: [Boolean, Function] },
+    qux: {}
+  }, { ...defaults }),
+  setup(__props: any, { expose: __expose }) {
+  __expose();
+
+const props = __props;
+
+    
+    
+return { props, get defaults() { return defaults } }
+}
+
+})"
+`;
+
+exports[`defineProps > 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;
+
+    
+    
+return { props, get defaults() { return defaults } }
+}
+
+})"
+`;
+
+exports[`defineProps > withDefaults (static) + normal script 1`] = `
+"import { defineComponent as _defineComponent } from 'vue'
+
+      interface Props {
+        a?: string;
+      }
+    
+export default /*#__PURE__*/_defineComponent({
+  props: {
+    a: { type: String, required: false, default: \\"a\\" }
+  },
+  setup(__props: any, { expose: __expose }) {
+  __expose();
+
+const props = __props;
+
+      
+    
+return { props }
+}
+
+})"
+`;
+
+exports[`defineProps > withDefaults (static) 1`] = `
+"import { defineComponent as _defineComponent } from 'vue'
+
+export default /*#__PURE__*/_defineComponent({
+  props: {
+    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 } },
+    quux: { type: Function, required: false, default() { } },
+    quuxx: { type: Promise, required: false, async default() { return await Promise.resolve('hi') } },
+    fred: { type: String, required: false, get default() { return 'fred' } }
+  },
+  setup(__props: any, { expose: __expose }) {
+  __expose();
+
+const props = __props;
+
+    
+    
+return { props }
+}
+
+})"
+`;
+
+exports[`defineProps > withDefaults (static) w/ production mode 1`] = `
+"import { defineComponent as _defineComponent } from 'vue'
+
+export default /*#__PURE__*/_defineComponent({
+  props: {
+    foo: {},
+    bar: { type: Boolean },
+    baz: { type: [Boolean, Function], default: true },
+    qux: { default: 'hi' }
+  },
+  setup(__props: any, { expose: __expose }) {
+  __expose();
+
+const props = __props;
+
+    
+    
+return { props }
+}
+
+})"
+`;
+
+exports[`defineProps > withDefaults w/ dynamic object method 1`] = `
+"import { mergeDefaults as _mergeDefaults, defineComponent as _defineComponent } from 'vue'
+
+export default /*#__PURE__*/_defineComponent({
+  props: _mergeDefaults({
+    foo: { type: Function, required: false }
+  }, {
+      ['fo' + 'o']() { return 'foo' }
+    }),
+  setup(__props: any, { expose: __expose }) {
+  __expose();
+
+const props = __props;
+
+    
+    
+return { props }
+}
+
+})"
+`;
diff --git a/packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineSlots.spec.ts.snap b/packages/compiler-sfc/__tests__/compileScript/__snapshots__/defineSlots.spec.ts.snap
new file mode 100644 (file)
index 0000000..26e1a0c
--- /dev/null
@@ -0,0 +1,46 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`defineSlots() > basic usage 1`] = `
+"import { useSlots as _useSlots, defineComponent as _defineComponent } from 'vue'
+
+export default /*#__PURE__*/_defineComponent({
+  setup(__props, { expose: __expose }) {
+  __expose();
+
+      const slots = _useSlots()
+      
+return { slots }
+}
+
+})"
+`;
+
+exports[`defineSlots() > w/o generic params 1`] = `
+"import { useSlots as _useSlots } from 'vue'
+
+export default {
+  setup(__props, { expose: __expose }) {
+  __expose();
+
+      const slots = _useSlots()
+      
+return { slots }
+}
+
+}"
+`;
+
+exports[`defineSlots() > w/o return value 1`] = `
+"import { defineComponent as _defineComponent } from 'vue'
+
+export default /*#__PURE__*/_defineComponent({
+  setup(__props, { expose: __expose }) {
+  __expose();
+
+      
+      
+return {  }
+}
+
+})"
+`;
diff --git a/packages/compiler-sfc/__tests__/compileScript/defineEmits.spec.ts b/packages/compiler-sfc/__tests__/compileScript/defineEmits.spec.ts
new file mode 100644 (file)
index 0000000..3920f08
--- /dev/null
@@ -0,0 +1,204 @@
+import { BindingTypes } from '@vue/compiler-core'
+import { compileSFCScript as compile, assertCode } from '../utils'
+
+describe('defineEmits', () => {
+  test('basic usage', () => {
+    const { content, bindings } = compile(`
+<script setup>
+const myEmit = defineEmits(['foo', 'bar'])
+</script>
+  `)
+    assertCode(content)
+    expect(bindings).toStrictEqual({
+      myEmit: BindingTypes.SETUP_CONST
+    })
+    // should remove defineEmits import and call
+    expect(content).not.toMatch('defineEmits')
+    // should generate correct setup signature
+    expect(content).toMatch(
+      `setup(__props, { expose: __expose, emit: myEmit }) {`
+    )
+    // should include context options in default export
+    expect(content).toMatch(`export default {
+  emits: ['foo', 'bar'],`)
+  })
+
+  test('w/ runtime options', () => {
+    const { content } = compile(`
+<script setup lang="ts">
+const emit = defineEmits(['a', 'b'])
+</script>
+    `)
+    assertCode(content)
+    expect(content).toMatch(`export default /*#__PURE__*/_defineComponent({
+  emits: ['a', 'b'],
+  setup(__props, { expose: __expose, emit }) {`)
+  })
+
+  test('w/ type', () => {
+    const { content } = compile(`
+    <script setup lang="ts">
+    const emit = defineEmits<(e: 'foo' | 'bar') => void>()
+    </script>
+    `)
+    assertCode(content)
+    expect(content).toMatch(`emits: ["foo", "bar"]`)
+  })
+
+  test('w/ type (union)', () => {
+    const type = `((e: 'foo' | 'bar') => void) | ((e: 'baz', id: number) => void)`
+    expect(() =>
+      compile(`
+    <script setup lang="ts">
+    const emit = defineEmits<${type}>()
+    </script>
+    `)
+    ).toThrow()
+  })
+
+  test('w/ type (type literal w/ call signatures)', () => {
+    const type = `{(e: 'foo' | 'bar'): void; (e: 'baz', id: number): void;}`
+    const { content } = compile(`
+    <script setup lang="ts">
+    const emit = defineEmits<${type}>()
+    </script>
+    `)
+    assertCode(content)
+    expect(content).toMatch(`emits: ["foo", "bar", "baz"]`)
+  })
+
+  test('w/ type (interface)', () => {
+    const { content } = compile(`
+    <script setup lang="ts">
+    interface Emits { (e: 'foo' | 'bar'): void }
+    const emit = defineEmits<Emits>()
+    </script>
+    `)
+    assertCode(content)
+    expect(content).toMatch(`emits: ["foo", "bar"]`)
+  })
+
+  test('w/ type (exported interface)', () => {
+    const { content } = compile(`
+    <script setup lang="ts">
+    export interface Emits { (e: 'foo' | 'bar'): void }
+    const emit = defineEmits<Emits>()
+    </script>
+    `)
+    assertCode(content)
+    expect(content).toMatch(`emits: ["foo", "bar"]`)
+  })
+
+  test('w/ type from normal script', () => {
+    const { content } = compile(`
+    <script lang="ts">
+      export interface Emits { (e: 'foo' | 'bar'): void }
+    </script>
+    <script setup lang="ts">
+    const emit = defineEmits<Emits>()
+    </script>
+    `)
+    assertCode(content)
+    expect(content).toMatch(`emits: ["foo", "bar"]`)
+  })
+
+  test('w/ type (type alias)', () => {
+    const { content } = compile(`
+    <script setup lang="ts">
+    type Emits = { (e: 'foo' | 'bar'): void }
+    const emit = defineEmits<Emits>()
+    </script>
+    `)
+    assertCode(content)
+    expect(content).toMatch(`emits: ["foo", "bar"]`)
+  })
+
+  test('w/ type (exported type alias)', () => {
+    const { content } = compile(`
+    <script setup lang="ts">
+    export type Emits = { (e: 'foo' | 'bar'): void }
+    const emit = defineEmits<Emits>()
+    </script>
+    `)
+    assertCode(content)
+    expect(content).toMatch(`emits: ["foo", "bar"]`)
+  })
+
+  test('w/ type (referenced function type)', () => {
+    const { content } = compile(`
+    <script setup lang="ts">
+    type Emits = (e: 'foo' | 'bar') => void
+    const emit = defineEmits<Emits>()
+    </script>
+    `)
+    assertCode(content)
+    expect(content).toMatch(`emits: ["foo", "bar"]`)
+  })
+
+  test('w/ type (referenced exported function type)', () => {
+    const { content } = compile(`
+    <script setup lang="ts">
+    export type Emits = (e: 'foo' | 'bar') => void
+    const emit = defineEmits<Emits>()
+    </script>
+    `)
+    assertCode(content)
+    expect(content).toMatch(`emits: ["foo", "bar"]`)
+  })
+
+  // #5393
+  test('w/ type (interface ts type)', () => {
+    const { content } = compile(`
+    <script setup lang="ts">
+    interface Emits { (e: 'foo'): void }
+    const emit: Emits = defineEmits(['foo'])
+    </script>
+    `)
+    assertCode(content)
+    expect(content).toMatch(`emits: ['foo']`)
+  })
+
+  test('w/ type (property syntax)', () => {
+    const { content } = compile(`
+    <script setup lang="ts">
+    const emit = defineEmits<{ foo: [], bar: [] }>()
+    </script>
+    `)
+    expect(content).toMatch(`emits: ["foo", "bar"]`)
+    assertCode(content)
+  })
+
+  // #8040
+  test('w/ type (property syntax string literal)', () => {
+    const { content } = compile(`
+    <script setup lang="ts">
+    const emit = defineEmits<{ 'foo:bar': [] }>()
+    </script>
+    `)
+    expect(content).toMatch(`emits: ["foo:bar"]`)
+    assertCode(content)
+  })
+
+  describe('errors', () => {
+    test('w/ both type and non-type args', () => {
+      expect(() => {
+        compile(`<script setup lang="ts">
+        defineEmits<{}>({})
+        </script>`)
+      }).toThrow(`cannot accept both type and non-type arguments`)
+    })
+
+    test('mixed usage of property / call signature', () => {
+      expect(() =>
+        compile(`<script setup lang="ts">
+        defineEmits<{
+          foo: []
+          (e: 'hi'): void
+        }>()
+        </script>`)
+      ).toThrow(
+        `defineEmits() type cannot mixed call signature and property syntax.`
+      )
+    })
+  })
+})
diff --git a/packages/compiler-sfc/__tests__/compileScript/defineExpose.spec.ts b/packages/compiler-sfc/__tests__/compileScript/defineExpose.spec.ts
new file mode 100644 (file)
index 0000000..8ddd28a
--- /dev/null
@@ -0,0 +1,26 @@
+import { compileSFCScript as compile, assertCode } from '../utils'
+
+test('defineExpose()', () => {
+  const { content } = compile(`
+<script setup>
+defineExpose({ foo: 123 })
+</script>
+`)
+  assertCode(content)
+  // should remove defineOptions import and call
+  expect(content).not.toMatch('defineExpose')
+  // should generate correct setup signature
+  expect(content).toMatch(`setup(__props, { expose: __expose }) {`)
+  // should replace callee
+  expect(content).toMatch(/\b__expose\(\{ foo: 123 \}\)/)
+})
+
+test('<script> after <script setup> the script content not end with `\\n`', () => {
+  const { content } = compile(`
+  <script setup>
+  import { x } from './x'
+  </script>
+  <script>const n = 1</script>
+  `)
+  assertCode(content)
+})
diff --git a/packages/compiler-sfc/__tests__/compileScript/defineModel.spec.ts b/packages/compiler-sfc/__tests__/compileScript/defineModel.spec.ts
new file mode 100644 (file)
index 0000000..61a9adc
--- /dev/null
@@ -0,0 +1,179 @@
+import { BindingTypes } from '@vue/compiler-core'
+import { compileSFCScript as compile, assertCode } from '../utils'
+
+describe('defineModel()', () => {
+  test('basic usage', () => {
+    const { content, bindings } = compile(
+      `
+      <script setup>
+      const modelValue = defineModel({ required: true })
+      const c = defineModel('count')
+      </script>
+      `,
+      { defineModel: true }
+    )
+    assertCode(content)
+    expect(content).toMatch('props: {')
+    expect(content).toMatch('"modelValue": { required: true },')
+    expect(content).toMatch('"count": {},')
+    expect(content).toMatch('emits: ["update:modelValue", "update:count"],')
+    expect(content).toMatch(
+      `const modelValue = _useModel(__props, "modelValue")`
+    )
+    expect(content).toMatch(`const c = _useModel(__props, "count")`)
+    expect(content).toMatch(`return { modelValue, c }`)
+    expect(content).not.toMatch('defineModel')
+
+    expect(bindings).toStrictEqual({
+      modelValue: BindingTypes.SETUP_REF,
+      count: BindingTypes.PROPS,
+      c: BindingTypes.SETUP_REF
+    })
+  })
+
+  test('w/ defineProps and defineEmits', () => {
+    const { content, bindings } = compile(
+      `
+      <script setup>
+      defineProps({ foo: String })
+      defineEmits(['change'])
+      const count = defineModel({ default: 0 })
+      </script>
+    `,
+      { defineModel: true }
+    )
+    assertCode(content)
+    expect(content).toMatch(`props: _mergeModels({ foo: String }`)
+    expect(content).toMatch(`"modelValue": { default: 0 }`)
+    expect(content).toMatch(`const count = _useModel(__props, "modelValue")`)
+    expect(content).not.toMatch('defineModel')
+    expect(bindings).toStrictEqual({
+      count: BindingTypes.SETUP_REF,
+      foo: BindingTypes.PROPS,
+      modelValue: BindingTypes.PROPS
+    })
+  })
+
+  test('w/ array props', () => {
+    const { content, bindings } = compile(
+      `
+      <script setup>
+      defineProps(['foo', 'bar'])
+      const count = defineModel('count')
+      </script>
+    `,
+      { defineModel: true }
+    )
+    assertCode(content)
+    expect(content).toMatch(`props: _mergeModels(['foo', 'bar'], {
+    "count": {},
+  })`)
+    expect(content).toMatch(`const count = _useModel(__props, "count")`)
+    expect(content).not.toMatch('defineModel')
+    expect(bindings).toStrictEqual({
+      foo: BindingTypes.PROPS,
+      bar: BindingTypes.PROPS,
+      count: BindingTypes.SETUP_REF
+    })
+  })
+
+  test('w/ local flag', () => {
+    const { content } = compile(
+      `<script setup>
+      const foo = defineModel({ local: true, default: 1 })
+      const bar = defineModel('bar', { [key]: true })
+      const baz = defineModel('baz', { ...x })
+      const qux = defineModel('qux', x)
+
+      const foo2 = defineModel('foo2', { local: true, ...x })
+
+      const local = true
+      const hoist = defineModel('hoist', { local })
+      </script>`,
+      { defineModel: true }
+    )
+    assertCode(content)
+    expect(content).toMatch(`_useModel(__props, "modelValue", { local: true })`)
+    expect(content).toMatch(`_useModel(__props, "bar", { [key]: true })`)
+    expect(content).toMatch(`_useModel(__props, "baz", { ...x })`)
+    expect(content).toMatch(`_useModel(__props, "qux", x)`)
+    expect(content).toMatch(`_useModel(__props, "foo2", { local: true })`)
+    expect(content).toMatch(`_useModel(__props, "hoist", { local })`)
+  })
+
+  test('w/ types, basic usage', () => {
+    const { content, bindings } = compile(
+      `
+      <script setup lang="ts">
+      const modelValue = defineModel<boolean | string>()
+      const count = defineModel<number>('count')
+      const disabled = defineModel<number>('disabled', { required: false })
+      const any = defineModel<any | boolean>('any')
+      </script>
+      `,
+      { defineModel: true }
+    )
+    assertCode(content)
+    expect(content).toMatch('"modelValue": { type: [Boolean, String] }')
+    expect(content).toMatch('"count": { type: Number }')
+    expect(content).toMatch(
+      '"disabled": { type: Number, ...{ required: false } }'
+    )
+    expect(content).toMatch('"any": { type: Boolean, skipCheck: true }')
+    expect(content).toMatch(
+      'emits: ["update:modelValue", "update:count", "update:disabled", "update:any"]'
+    )
+
+    expect(content).toMatch(
+      `const modelValue = _useModel(__props, "modelValue")`
+    )
+    expect(content).toMatch(`const count = _useModel(__props, "count")`)
+    expect(content).toMatch(`const disabled = _useModel(__props, "disabled")`)
+    expect(content).toMatch(`const any = _useModel(__props, "any")`)
+
+    expect(bindings).toStrictEqual({
+      modelValue: BindingTypes.SETUP_REF,
+      count: BindingTypes.SETUP_REF,
+      disabled: BindingTypes.SETUP_REF,
+      any: BindingTypes.SETUP_REF
+    })
+  })
+
+  test('w/ types, production mode', () => {
+    const { content, bindings } = compile(
+      `
+      <script setup lang="ts">
+      const modelValue = defineModel<boolean>()
+      const fn = defineModel<() => void>('fn')
+      const fnWithDefault = defineModel<() => void>('fnWithDefault', { default: () => null })
+      const str = defineModel<string>('str')
+      const optional = defineModel<string>('optional', { required: false })
+      </script>
+      `,
+      { defineModel: true, isProd: true }
+    )
+    assertCode(content)
+    expect(content).toMatch('"modelValue": { type: Boolean }')
+    expect(content).toMatch('"fn": {}')
+    expect(content).toMatch(
+      '"fnWithDefault": { type: Function, ...{ default: () => null } },'
+    )
+    expect(content).toMatch('"str": {}')
+    expect(content).toMatch('"optional": { required: false }')
+    expect(content).toMatch(
+      'emits: ["update:modelValue", "update:fn", "update:fnWithDefault", "update:str", "update:optional"]'
+    )
+    expect(content).toMatch(
+      `const modelValue = _useModel(__props, "modelValue")`
+    )
+    expect(content).toMatch(`const fn = _useModel(__props, "fn")`)
+    expect(content).toMatch(`const str = _useModel(__props, "str")`)
+    expect(bindings).toStrictEqual({
+      modelValue: BindingTypes.SETUP_REF,
+      fn: BindingTypes.SETUP_REF,
+      fnWithDefault: BindingTypes.SETUP_REF,
+      str: BindingTypes.SETUP_REF,
+      optional: BindingTypes.SETUP_REF
+    })
+  })
+})
diff --git a/packages/compiler-sfc/__tests__/compileScript/defineOptions.spec.ts b/packages/compiler-sfc/__tests__/compileScript/defineOptions.spec.ts
new file mode 100644 (file)
index 0000000..5337a53
--- /dev/null
@@ -0,0 +1,149 @@
+import { compileSFCScript as compile, assertCode } from '../utils'
+
+describe('defineOptions()', () => {
+  test('basic usage', () => {
+    const { content } = compile(`
+      <script setup>
+      defineOptions({ name: 'FooApp' })
+      </script>
+    `)
+    assertCode(content)
+    // should remove defineOptions import and call
+    expect(content).not.toMatch('defineOptions')
+    // should include context options in default export
+    expect(content).toMatch(
+      `export default /*#__PURE__*/Object.assign({ 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(`
+      <script setup>
+      defineOptions({ name: 'FooApp' })
+      defineOptions({ name: 'BarApp' })
+      </script>
+      `)
+    ).toThrowError('[@vue/compiler-sfc] duplicate defineOptions() call')
+  })
+
+  it('should emit an error with props or emits property', () => {
+    expect(() =>
+      compile(`
+      <script setup>
+      defineOptions({ props: { foo: String } })
+      </script>
+      `)
+    ).toThrowError(
+      '[@vue/compiler-sfc] defineOptions() cannot be used to declare props. Use defineProps() instead.'
+    )
+
+    expect(() =>
+      compile(`
+      <script setup>
+      defineOptions({ emits: ['update'] })
+      </script>
+    `)
+    ).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', () => {
+    expect(() =>
+      compile(`
+      <script setup lang="ts">
+      defineOptions<{ name: 'FooApp' }>()
+      </script>
+      `)
+    ).toThrowError(
+      '[@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.'
+    )
+  })
+
+  it('should emit an error with declaring props/emits/slots/expose', () => {
+    expect(() =>
+      compile(`
+        <script setup>
+        defineOptions({ props: ['foo'] })
+        </script>
+      `)
+    ).toThrowError(
+      '[@vue/compiler-sfc] defineOptions() cannot be used to declare props. Use defineProps() instead'
+    )
+
+    expect(() =>
+      compile(`
+        <script setup>
+        defineOptions({ emits: ['update'] })
+        </script>
+      `)
+    ).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 lang="ts">
+        defineOptions({ slots: Object })
+        </script>
+      `)
+    ).toThrowError(
+      '[@vue/compiler-sfc] defineOptions() cannot be used to declare slots. Use defineSlots() instead'
+    )
+  })
+})
diff --git a/packages/compiler-sfc/__tests__/compileScript/defineProps.spec.ts b/packages/compiler-sfc/__tests__/compileScript/defineProps.spec.ts
new file mode 100644 (file)
index 0000000..cf61c98
--- /dev/null
@@ -0,0 +1,583 @@
+import { BindingTypes } from '@vue/compiler-core'
+import { compileSFCScript as compile, assertCode } from '../utils'
+
+describe('defineProps', () => {
+  test('basic usage', () => {
+    const { content, bindings } = compile(`
+<script setup>
+const props = defineProps({
+  foo: String
+})
+const bar = 1
+</script>
+  `)
+    // should generate working code
+    assertCode(content)
+    // should analyze bindings
+    expect(bindings).toStrictEqual({
+      foo: BindingTypes.PROPS,
+      bar: BindingTypes.LITERAL_CONST,
+      props: BindingTypes.SETUP_REACTIVE_CONST
+    })
+
+    // should remove defineOptions import and call
+    expect(content).not.toMatch('defineProps')
+    // should generate correct setup signature
+    expect(content).toMatch(`setup(__props, { expose: __expose }) {`)
+    // should assign user identifier to it
+    expect(content).toMatch(`const props = __props`)
+    // should include context options in default export
+    expect(content).toMatch(`export default {
+  props: {
+  foo: String
+},`)
+  })
+
+  test('w/ external definition', () => {
+    const { content } = compile(`
+    <script setup>
+    import { propsModel } from './props'
+    const props = defineProps(propsModel)
+    </script>
+      `)
+    assertCode(content)
+    expect(content).toMatch(`export default {
+  props: propsModel,`)
+  })
+
+  // #4764
+  test('w/ leading code', () => {
+    const { content } = compile(`
+    <script setup>import { x } from './x'
+    const props = defineProps({})
+    </script>
+    `)
+    // props declaration should be inside setup, not moved along with the import
+    expect(content).not.toMatch(`const props = __props\nimport`)
+    assertCode(content)
+  })
+
+  test('defineProps w/ runtime options', () => {
+    const { content } = compile(`
+<script setup lang="ts">
+const props = defineProps({ foo: String })
+</script>
+    `)
+    assertCode(content)
+    expect(content).toMatch(`export default /*#__PURE__*/_defineComponent({
+  props: { foo: String },
+  setup(__props, { expose: __expose }) {`)
+  })
+
+  test('w/ type', () => {
+    const { content, bindings } = compile(`
+    <script setup lang="ts">
+    interface Test {}
+
+    type Alias = number[]
+
+    defineProps<{
+      string: string
+      number: number
+      boolean: boolean
+      object: object
+      objectLiteral: { a: number }
+      fn: (n: number) => void
+      functionRef: Function
+      objectRef: Object
+      dateTime: Date
+      array: string[]
+      arrayRef: Array<any>
+      tuple: [number, number]
+      set: Set<string>
+      literal: 'foo'
+      optional?: any
+      recordRef: Record<string, null>
+      interface: Test
+      alias: Alias
+      method(): void
+      symbol: symbol
+      extract: Extract<1 | 2 | boolean, 2>
+      exclude: Exclude<1 | 2 | boolean, 2>
+      uppercase: Uppercase<'foo'>
+      params: Parameters<(foo: any) => void>
+      nonNull: NonNullable<string | null>
+      objectOrFn: {
+        (): void
+        foo: string
+      }
+
+      union: string | number
+      literalUnion: 'foo' | 'bar'
+      literalUnionNumber: 1 | 2 | 3 | 4 | 5
+      literalUnionMixed: 'foo' | 1 | boolean
+      intersection: Test & {}
+      intersection2: 'foo' & ('foo' | 'bar')
+      foo: ((item: any) => boolean) | null
+
+      unknown: UnknownType
+      unknownUnion: UnknownType | string
+      unknownIntersection: UnknownType & Object
+      unknownUnionWithBoolean: UnknownType | boolean
+      unknownUnionWithFunction: UnknownType | (() => any)
+    }>()
+    </script>`)
+    assertCode(content)
+    expect(content).toMatch(`string: { type: String, required: true }`)
+    expect(content).toMatch(`number: { type: Number, required: true }`)
+    expect(content).toMatch(`boolean: { type: Boolean, required: true }`)
+    expect(content).toMatch(`object: { type: Object, required: true }`)
+    expect(content).toMatch(`objectLiteral: { type: Object, required: true }`)
+    expect(content).toMatch(`fn: { type: Function, required: true }`)
+    expect(content).toMatch(`functionRef: { type: Function, required: true }`)
+    expect(content).toMatch(`objectRef: { type: Object, required: true }`)
+    expect(content).toMatch(`dateTime: { type: Date, required: true }`)
+    expect(content).toMatch(`array: { type: Array, required: true }`)
+    expect(content).toMatch(`arrayRef: { type: Array, required: true }`)
+    expect(content).toMatch(`tuple: { type: Array, required: true }`)
+    expect(content).toMatch(`set: { type: Set, required: true }`)
+    expect(content).toMatch(`literal: { type: String, required: true }`)
+    expect(content).toMatch(`optional: { type: null, required: false }`)
+    expect(content).toMatch(`recordRef: { type: Object, required: true }`)
+    expect(content).toMatch(`interface: { type: Object, required: true }`)
+    expect(content).toMatch(`alias: { type: Array, required: true }`)
+    expect(content).toMatch(`method: { type: Function, required: true }`)
+    expect(content).toMatch(`symbol: { type: Symbol, required: true }`)
+    expect(content).toMatch(
+      `objectOrFn: { type: [Function, Object], required: true },`
+    )
+    expect(content).toMatch(`extract: { type: Number, required: true }`)
+    expect(content).toMatch(
+      `exclude: { type: [Number, Boolean], required: true }`
+    )
+    expect(content).toMatch(`uppercase: { type: String, required: true }`)
+    expect(content).toMatch(`params: { type: Array, required: true }`)
+    expect(content).toMatch(`nonNull: { type: String, required: true }`)
+    expect(content).toMatch(`union: { type: [String, Number], required: true }`)
+    expect(content).toMatch(`literalUnion: { type: String, required: true }`)
+    expect(content).toMatch(
+      `literalUnionNumber: { type: Number, required: true }`
+    )
+    expect(content).toMatch(
+      `literalUnionMixed: { type: [String, Number, Boolean], required: true }`
+    )
+    expect(content).toMatch(`intersection: { type: Object, required: true }`)
+    expect(content).toMatch(`intersection2: { type: String, required: true }`)
+    expect(content).toMatch(`foo: { type: [Function, null], required: true }`)
+    expect(content).toMatch(`unknown: { type: null, required: true }`)
+    // uninon containing unknown type: skip check
+    expect(content).toMatch(`unknownUnion: { type: null, required: true }`)
+    // intersection containing unknown type: narrow to the known types
+    expect(content).toMatch(
+      `unknownIntersection: { type: Object, required: true },`
+    )
+    expect(content).toMatch(
+      `unknownUnionWithBoolean: { type: Boolean, required: true, skipCheck: true },`
+    )
+    expect(content).toMatch(
+      `unknownUnionWithFunction: { type: Function, required: true, skipCheck: true }`
+    )
+    expect(bindings).toStrictEqual({
+      string: BindingTypes.PROPS,
+      number: BindingTypes.PROPS,
+      boolean: BindingTypes.PROPS,
+      object: BindingTypes.PROPS,
+      objectLiteral: BindingTypes.PROPS,
+      fn: BindingTypes.PROPS,
+      functionRef: BindingTypes.PROPS,
+      objectRef: BindingTypes.PROPS,
+      dateTime: BindingTypes.PROPS,
+      array: BindingTypes.PROPS,
+      arrayRef: BindingTypes.PROPS,
+      tuple: BindingTypes.PROPS,
+      set: BindingTypes.PROPS,
+      literal: BindingTypes.PROPS,
+      optional: BindingTypes.PROPS,
+      recordRef: BindingTypes.PROPS,
+      interface: BindingTypes.PROPS,
+      alias: BindingTypes.PROPS,
+      method: BindingTypes.PROPS,
+      symbol: BindingTypes.PROPS,
+      objectOrFn: BindingTypes.PROPS,
+      extract: BindingTypes.PROPS,
+      exclude: BindingTypes.PROPS,
+      union: BindingTypes.PROPS,
+      literalUnion: BindingTypes.PROPS,
+      literalUnionNumber: BindingTypes.PROPS,
+      literalUnionMixed: BindingTypes.PROPS,
+      intersection: BindingTypes.PROPS,
+      intersection2: BindingTypes.PROPS,
+      foo: BindingTypes.PROPS,
+      uppercase: BindingTypes.PROPS,
+      params: BindingTypes.PROPS,
+      nonNull: BindingTypes.PROPS,
+      unknown: BindingTypes.PROPS,
+      unknownUnion: BindingTypes.PROPS,
+      unknownIntersection: BindingTypes.PROPS,
+      unknownUnionWithBoolean: BindingTypes.PROPS,
+      unknownUnionWithFunction: BindingTypes.PROPS
+    })
+  })
+
+  test('w/ interface', () => {
+    const { content, bindings } = compile(`
+    <script setup lang="ts">
+    interface Props { x?: number }
+    defineProps<Props>()
+    </script>
+    `)
+    assertCode(content)
+    expect(content).toMatch(`x: { type: Number, required: false }`)
+    expect(bindings).toStrictEqual({
+      x: BindingTypes.PROPS
+    })
+  })
+
+  test('w/ extends interface', () => {
+    const { content, bindings } = compile(`
+    <script lang="ts">
+      interface Foo { x?: number }
+    </script>
+    <script setup lang="ts">
+      interface Bar extends Foo { y?: number }
+      interface Props extends Bar {
+        z: number
+        y: string
+      }
+      defineProps<Props>()
+    </script>
+    `)
+    assertCode(content)
+    expect(content).toMatch(`z: { type: Number, required: true }`)
+    expect(content).toMatch(`y: { type: String, required: true }`)
+    expect(content).toMatch(`x: { type: Number, required: false }`)
+    expect(bindings).toStrictEqual({
+      x: BindingTypes.PROPS,
+      y: BindingTypes.PROPS,
+      z: BindingTypes.PROPS
+    })
+  })
+
+  test('w/ exported interface', () => {
+    const { content, bindings } = compile(`
+    <script setup lang="ts">
+    export interface Props { x?: number }
+    defineProps<Props>()
+    </script>
+    `)
+    assertCode(content)
+    expect(content).toMatch(`x: { type: Number, required: false }`)
+    expect(bindings).toStrictEqual({
+      x: BindingTypes.PROPS
+    })
+  })
+
+  test('w/ exported interface in normal script', () => {
+    const { content, bindings } = compile(`
+    <script lang="ts">
+      export interface Props { x?: number }
+    </script>
+    <script setup lang="ts">
+      defineProps<Props>()
+    </script>
+    `)
+    assertCode(content)
+    expect(content).toMatch(`x: { type: Number, required: false }`)
+    expect(bindings).toStrictEqual({
+      x: BindingTypes.PROPS
+    })
+  })
+
+  test('w/ type alias', () => {
+    const { content, bindings } = compile(`
+    <script setup lang="ts">
+    type Props = { x?: number }
+    defineProps<Props>()
+    </script>
+    `)
+    assertCode(content)
+    expect(content).toMatch(`x: { type: Number, required: false }`)
+    expect(bindings).toStrictEqual({
+      x: BindingTypes.PROPS
+    })
+  })
+
+  test('w/ exported type alias', () => {
+    const { content, bindings } = compile(`
+    <script setup lang="ts">
+    export type Props = { x?: number }
+    defineProps<Props>()
+    </script>
+    `)
+    assertCode(content)
+    expect(content).toMatch(`x: { type: Number, required: false }`)
+    expect(bindings).toStrictEqual({
+      x: BindingTypes.PROPS
+    })
+  })
+
+  test('w/ TS assertion', () => {
+    const { content, bindings } = compile(`
+    <script setup lang="ts">
+      defineProps(['foo'])! as any
+    </script>
+  `)
+    expect(content).toMatch(`props: ['foo']`)
+    assertCode(content)
+    expect(bindings).toStrictEqual({
+      foo: BindingTypes.PROPS
+    })
+  })
+
+  test('withDefaults (static)', () => {
+    const { content, bindings } = compile(`
+    <script setup lang="ts">
+    const props = withDefaults(defineProps<{
+      foo?: string
+      bar?: number;
+      baz: boolean;
+      qux?(): number;
+      quux?(): void
+      quuxx?: Promise<string>;
+      fred?: string
+    }>(), {
+      foo: 'hi',
+      qux() { return 1 },
+      ['quux']() { },
+      async quuxx() { return await Promise.resolve('hi') },
+      get fred() { return 'fred' }
+    })
+    </script>
+    `)
+    assertCode(content)
+    expect(content).toMatch(
+      `foo: { type: String, required: false, default: 'hi' }`
+    )
+    expect(content).toMatch(`bar: { type: Number, required: false }`)
+    expect(content).toMatch(`baz: { type: Boolean, required: true }`)
+    expect(content).toMatch(
+      `qux: { type: Function, required: false, default() { return 1 } }`
+    )
+    expect(content).toMatch(
+      `quux: { type: Function, required: false, default() { } }`
+    )
+    expect(content).toMatch(
+      `quuxx: { type: Promise, required: false, async default() { return await Promise.resolve('hi') } }`
+    )
+    expect(content).toMatch(
+      `fred: { type: String, required: false, get default() { return 'fred' } }`
+    )
+    expect(content).toMatch(`const props = __props`)
+    expect(bindings).toStrictEqual({
+      foo: BindingTypes.PROPS,
+      bar: BindingTypes.PROPS,
+      baz: BindingTypes.PROPS,
+      qux: BindingTypes.PROPS,
+      quux: BindingTypes.PROPS,
+      quuxx: BindingTypes.PROPS,
+      fred: BindingTypes.PROPS,
+      props: BindingTypes.SETUP_CONST
+    })
+  })
+
+  test('withDefaults (static) + normal script', () => {
+    const { content } = compile(`
+    <script lang="ts">
+      interface Props {
+        a?: string;
+      }
+    </script>
+    <script setup lang="ts">
+      const props = withDefaults(defineProps<Props>(), {
+        a: "a",
+      });
+    </script>
+    `)
+    assertCode(content)
+  })
+
+  // #7111
+  test('withDefaults (static) w/ production mode', () => {
+    const { content } = compile(
+      `
+    <script setup lang="ts">
+    const props = withDefaults(defineProps<{
+      foo: () => void
+      bar: boolean
+      baz: boolean | (() => void)
+      qux: string | number
+    }>(), {
+      baz: true,
+      qux: 'hi'
+    })
+    </script>
+    `,
+      { isProd: true }
+    )
+    assertCode(content)
+    expect(content).toMatch(`const props = __props`)
+
+    // foo has no default value, the Function can be dropped
+    expect(content).toMatch(`foo: {}`)
+    expect(content).toMatch(`bar: { type: Boolean }`)
+    expect(content).toMatch(`baz: { type: [Boolean, Function], default: true }`)
+    expect(content).toMatch(`qux: { default: 'hi' }`)
+  })
+
+  test('withDefaults (dynamic)', () => {
+    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()
+    )
+  })
+
+  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
+  test('withDefaults (dynamic) w/ production mode', () => {
+    const { content } = compile(
+      `
+    <script setup lang="ts">
+    import { defaults } from './foo'
+    const props = withDefaults(defineProps<{
+      foo: () => void
+      bar: boolean
+      baz: boolean | (() => void)
+      qux: string | number
+    }>(), { ...defaults })
+    </script>
+    `,
+      { isProd: true }
+    )
+    assertCode(content)
+    expect(content).toMatch(`import { mergeDefaults as _mergeDefaults`)
+    expect(content).toMatch(
+      `
+  _mergeDefaults({
+    foo: { type: Function },
+    bar: { type: Boolean },
+    baz: { type: [Boolean, Function] },
+    qux: {}
+  }, { ...defaults })`.trim()
+    )
+  })
+
+  test('withDefaults w/ dynamic object method', () => {
+    const { content } = compile(`
+    <script setup lang="ts">
+    const props = withDefaults(defineProps<{
+      foo?: () => 'string'
+    }>(), {
+      ['fo' + 'o']() { return 'foo' }
+    })
+    </script>
+    `)
+    assertCode(content)
+    expect(content).toMatch(`import { mergeDefaults as _mergeDefaults`)
+    expect(content).toMatch(
+      `
+  _mergeDefaults({
+    foo: { type: Function, required: false }
+  }, {
+      ['fo' + 'o']() { return 'foo' }
+    })`.trim()
+    )
+  })
+
+  test('runtime inference for Enum', () => {
+    expect(
+      compile(
+        `<script setup lang="ts">
+      const enum Foo { A = 123 }
+      defineProps<{
+        foo: Foo
+      }>()
+      </script>`,
+        { hoistStatic: true }
+      ).content
+    ).toMatch(`foo: { type: Number`)
+
+    expect(
+      compile(
+        `<script setup lang="ts">
+      const enum Foo { A = '123' }
+      defineProps<{
+        foo: Foo
+      }>()
+      </script>`,
+        { hoistStatic: true }
+      ).content
+    ).toMatch(`foo: { type: String`)
+
+    expect(
+      compile(
+        `<script setup lang="ts">
+      const enum Foo { A = '123', B = 123 }
+      defineProps<{
+        foo: Foo
+      }>()
+      </script>`,
+        { hoistStatic: true }
+      ).content
+    ).toMatch(`foo: { type: [String, Number]`)
+
+    expect(
+      compile(
+        `<script setup lang="ts">
+      const enum Foo { A, B }
+      defineProps<{
+        foo: Foo
+      }>()
+      </script>`,
+        { hoistStatic: true }
+      ).content
+    ).toMatch(`foo: { type: Number`)
+  })
+
+  describe('errors', () => {
+    test('w/ both type and non-type args', () => {
+      expect(() => {
+        compile(`<script setup lang="ts">
+        defineProps<{}>({})
+        </script>`)
+      }).toThrow(`cannot accept both type and non-type arguments`)
+    })
+  })
+})
similarity index 99%
rename from packages/compiler-sfc/__tests__/compileScriptPropsDestructure.spec.ts
rename to packages/compiler-sfc/__tests__/compileScript/definePropsDestructure.spec.ts
index e00d7d48b97ea5cdf14103903d4674262fe0cd67..a459d80ff298762f62b6f5c252a3ad097f71b27b 100644 (file)
@@ -1,6 +1,6 @@
 import { BindingTypes } from '@vue/compiler-core'
-import { SFCScriptCompileOptions } from '../src'
-import { compileSFCScript, assertCode } from './utils'
+import { SFCScriptCompileOptions } from '../../src'
+import { compileSFCScript, assertCode } from '../utils'
 
 describe('sfc props transform', () => {
   function compile(src: string, options?: Partial<SFCScriptCompileOptions>) {
diff --git a/packages/compiler-sfc/__tests__/compileScript/defineSlots.spec.ts b/packages/compiler-sfc/__tests__/compileScript/defineSlots.spec.ts
new file mode 100644 (file)
index 0000000..c7becac
--- /dev/null
@@ -0,0 +1,40 @@
+import { compileSFCScript as compile, assertCode } from '../utils'
+
+describe('defineSlots()', () => {
+  test('basic usage', () => {
+    const { content } = compile(`
+      <script setup lang="ts">
+      const slots = defineSlots<{
+        default: { msg: string }
+      }>()
+      </script>
+    `)
+    assertCode(content)
+    expect(content).toMatch(`const slots = _useSlots()`)
+    expect(content).not.toMatch('defineSlots')
+  })
+
+  test('w/o return value', () => {
+    const { content } = compile(`
+      <script setup lang="ts">
+      defineSlots<{
+        default: { msg: string }
+      }>()
+      </script>
+    `)
+    assertCode(content)
+    expect(content).not.toMatch('defineSlots')
+    expect(content).not.toMatch(`_useSlots`)
+  })
+
+  test('w/o generic params', () => {
+    const { content } = compile(`
+      <script setup>
+      const slots = defineSlots()
+      </script>
+    `)
+    assertCode(content)
+    expect(content).toMatch(`const slots = _useSlots()`)
+    expect(content).not.toMatch('defineSlots')
+  })
+})
similarity index 97%
rename from packages/compiler-sfc/__tests__/compileScriptHoistStatic.spec.ts
rename to packages/compiler-sfc/__tests__/compileScript/hoistStatic.spec.ts
index 4879dd5f924ede9d96d6349b5d5b7eead7ca8a2a..614a5e75bceb30e74bacc3ad40f5f63ae60084ee 100644 (file)
@@ -1,6 +1,6 @@
 import { BindingTypes } from '@vue/compiler-core'
-import { SFCScriptCompileOptions } from '../src'
-import { compileSFCScript, assertCode } from './utils'
+import { SFCScriptCompileOptions } from '../../src'
+import { compileSFCScript, assertCode } from '../utils'
 
 describe('sfc hoist static', () => {
   function compile(src: string, options?: Partial<SFCScriptCompileOptions>) {
similarity index 98%
rename from packages/compiler-sfc/__tests__/compileScriptRefTransform.spec.ts
rename to packages/compiler-sfc/__tests__/compileScript/reactivityTransform.spec.ts
index 8ae5275661e76a4ef59dd7da0411838600334f8e..44d51c14e75e5bcae4b4ead16947e8e56b0c9907 100644 (file)
@@ -1,5 +1,6 @@
+// TODO remove in 3.4
 import { BindingTypes } from '@vue/compiler-core'
-import { compileSFCScript as compile, assertCode } from './utils'
+import { compileSFCScript as compile, assertCode } from '../utils'
 
 // this file only tests integration with SFC - main test case for the ref
 // transform can be found in <root>/packages/reactivity-transform/__tests__