wip: test for runtime props/emits extraction
This commit is contained in:
		
							parent
							
								
									2c3cdab93d
								
							
						
					
					
						commit
						18c537d3c2
					
				@ -1,5 +1,92 @@
 | 
				
			|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
 | 
					// Jest Snapshot v1, https://goo.gl/fbAQLP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exports[`SFC compile <script setup> <script setup lang="ts"> extract emits 1`] = `
 | 
				
			||||||
 | 
					"import { defineComponent as __define__ } from 'vue'
 | 
				
			||||||
 | 
					import { Slots as __Slots__ } from 'vue'
 | 
				
			||||||
 | 
					declare function __emit__(e: 'foo' | 'bar'): void
 | 
				
			||||||
 | 
					      declare function __emit__(e: 'baz', id: number): void
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					export function setup(_: {}, { emit: myEmit }: {
 | 
				
			||||||
 | 
					  emit: typeof __emit__,
 | 
				
			||||||
 | 
					  slots: __Slots__,
 | 
				
			||||||
 | 
					  attrs: Record<string, any>
 | 
				
			||||||
 | 
					}) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					return {  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default __define__({
 | 
				
			||||||
 | 
					  emits: [\\"foo\\", \\"bar\\", \\"baz\\"] as unknown as undefined,
 | 
				
			||||||
 | 
					  setup
 | 
				
			||||||
 | 
					})"
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exports[`SFC compile <script setup> <script setup lang="ts"> extract props 1`] = `
 | 
				
			||||||
 | 
					"import { defineComponent as __define__ } from 'vue'
 | 
				
			||||||
 | 
					import { Slots as __Slots__ } from 'vue'
 | 
				
			||||||
 | 
					interface Test {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      type Alias = number[]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					export function setup(myProps: {
 | 
				
			||||||
 | 
					        string: string
 | 
				
			||||||
 | 
					        number: number
 | 
				
			||||||
 | 
					        boolean: boolean
 | 
				
			||||||
 | 
					        object: object
 | 
				
			||||||
 | 
					        objectLiteral: { a: number }
 | 
				
			||||||
 | 
					        fn: (n: number) => void
 | 
				
			||||||
 | 
					        functionRef: Function
 | 
				
			||||||
 | 
					        objectRef: Object
 | 
				
			||||||
 | 
					        array: string[]
 | 
				
			||||||
 | 
					        arrayRef: Array<any>
 | 
				
			||||||
 | 
					        tuple: [number, number]
 | 
				
			||||||
 | 
					        set: Set<string>
 | 
				
			||||||
 | 
					        literal: 'foo'
 | 
				
			||||||
 | 
					        optional?: any
 | 
				
			||||||
 | 
					        recordRef: Record<string, null>
 | 
				
			||||||
 | 
					        interface: Test
 | 
				
			||||||
 | 
					        alias: Alias
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        union: string | number
 | 
				
			||||||
 | 
					        literalUnion: 'foo' | 'bar'
 | 
				
			||||||
 | 
					        literalUnionMixed: 'foo' | 1 | boolean
 | 
				
			||||||
 | 
					        intersection: Test & {}
 | 
				
			||||||
 | 
					      }) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					return {  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default __define__({
 | 
				
			||||||
 | 
					  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 },
 | 
				
			||||||
 | 
					    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 },
 | 
				
			||||||
 | 
					    union: { type: [String, Number], required: true },
 | 
				
			||||||
 | 
					    literalUnion: { type: [String, String], required: true },
 | 
				
			||||||
 | 
					    literalUnionMixed: { type: [String, Number, Boolean], required: true },
 | 
				
			||||||
 | 
					    intersection: { type: Object, required: true }
 | 
				
			||||||
 | 
					  } as unknown as undefined,
 | 
				
			||||||
 | 
					  setup
 | 
				
			||||||
 | 
					})"
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
exports[`SFC compile <script setup> <script setup lang="ts"> hoist type declarations 1`] = `
 | 
					exports[`SFC compile <script setup> <script setup lang="ts"> hoist type declarations 1`] = `
 | 
				
			||||||
"import { defineComponent as __define__ } from 'vue'
 | 
					"import { defineComponent as __define__ } from 'vue'
 | 
				
			||||||
import { Slots as __Slots__ } from 'vue'
 | 
					import { Slots as __Slots__ } from 'vue'
 | 
				
			||||||
 | 
				
			|||||||
@ -205,9 +205,82 @@ describe('SFC compile <script setup>', () => {
 | 
				
			|||||||
      expect(bindings).toStrictEqual({ a: 'setup' })
 | 
					      expect(bindings).toStrictEqual({ a: 'setup' })
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    test('extract props', () => {})
 | 
					    test('extract props', () => {
 | 
				
			||||||
 | 
					      const { code } = compile(`
 | 
				
			||||||
 | 
					      <script setup="myProps" lang="ts">
 | 
				
			||||||
 | 
					      interface Test {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    test('extract emits', () => {})
 | 
					      type Alias = number[]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      declare const myProps: {
 | 
				
			||||||
 | 
					        string: string
 | 
				
			||||||
 | 
					        number: number
 | 
				
			||||||
 | 
					        boolean: boolean
 | 
				
			||||||
 | 
					        object: object
 | 
				
			||||||
 | 
					        objectLiteral: { a: number }
 | 
				
			||||||
 | 
					        fn: (n: number) => void
 | 
				
			||||||
 | 
					        functionRef: Function
 | 
				
			||||||
 | 
					        objectRef: Object
 | 
				
			||||||
 | 
					        array: string[]
 | 
				
			||||||
 | 
					        arrayRef: Array<any>
 | 
				
			||||||
 | 
					        tuple: [number, number]
 | 
				
			||||||
 | 
					        set: Set<string>
 | 
				
			||||||
 | 
					        literal: 'foo'
 | 
				
			||||||
 | 
					        optional?: any
 | 
				
			||||||
 | 
					        recordRef: Record<string, null>
 | 
				
			||||||
 | 
					        interface: Test
 | 
				
			||||||
 | 
					        alias: Alias
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        union: string | number
 | 
				
			||||||
 | 
					        literalUnion: 'foo' | 'bar'
 | 
				
			||||||
 | 
					        literalUnionMixed: 'foo' | 1 | boolean
 | 
				
			||||||
 | 
					        intersection: Test & {}
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      </script>`)
 | 
				
			||||||
 | 
					      assertCode(code)
 | 
				
			||||||
 | 
					      expect(code).toMatch(`string: { type: String, required: true }`)
 | 
				
			||||||
 | 
					      expect(code).toMatch(`number: { type: Number, required: true }`)
 | 
				
			||||||
 | 
					      expect(code).toMatch(`boolean: { type: Boolean, required: true }`)
 | 
				
			||||||
 | 
					      expect(code).toMatch(`object: { type: Object, required: true }`)
 | 
				
			||||||
 | 
					      expect(code).toMatch(`objectLiteral: { type: Object, required: true }`)
 | 
				
			||||||
 | 
					      expect(code).toMatch(`fn: { type: Function, required: true }`)
 | 
				
			||||||
 | 
					      expect(code).toMatch(`functionRef: { type: Function, required: true }`)
 | 
				
			||||||
 | 
					      expect(code).toMatch(`objectRef: { type: Object, required: true }`)
 | 
				
			||||||
 | 
					      expect(code).toMatch(`array: { type: Array, required: true }`)
 | 
				
			||||||
 | 
					      expect(code).toMatch(`arrayRef: { type: Array, required: true }`)
 | 
				
			||||||
 | 
					      expect(code).toMatch(`tuple: { type: Array, required: true }`)
 | 
				
			||||||
 | 
					      expect(code).toMatch(`set: { type: Set, required: true }`)
 | 
				
			||||||
 | 
					      expect(code).toMatch(`literal: { type: String, required: true }`)
 | 
				
			||||||
 | 
					      expect(code).toMatch(`optional: { type: null, required: false }`)
 | 
				
			||||||
 | 
					      expect(code).toMatch(`recordRef: { type: Object, required: true }`)
 | 
				
			||||||
 | 
					      expect(code).toMatch(`interface: { type: Object, required: true }`)
 | 
				
			||||||
 | 
					      expect(code).toMatch(`alias: { type: Array, required: true }`)
 | 
				
			||||||
 | 
					      expect(code).toMatch(`union: { type: [String, Number], required: true }`)
 | 
				
			||||||
 | 
					      expect(code).toMatch(
 | 
				
			||||||
 | 
					        `literalUnion: { type: [String, String], required: true }`
 | 
				
			||||||
 | 
					      )
 | 
				
			||||||
 | 
					      expect(code).toMatch(
 | 
				
			||||||
 | 
					        `literalUnionMixed: { type: [String, Number, Boolean], required: true }`
 | 
				
			||||||
 | 
					      )
 | 
				
			||||||
 | 
					      expect(code).toMatch(`intersection: { type: Object, required: true }`)
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    test('extract emits', () => {
 | 
				
			||||||
 | 
					      const { code } = compile(`
 | 
				
			||||||
 | 
					      <script setup="_, { emit: myEmit }" lang="ts">
 | 
				
			||||||
 | 
					      declare function myEmit(e: 'foo' | 'bar'): void
 | 
				
			||||||
 | 
					      declare function myEmit(e: 'baz', id: number): void
 | 
				
			||||||
 | 
					      </script>
 | 
				
			||||||
 | 
					      `)
 | 
				
			||||||
 | 
					      assertCode(code)
 | 
				
			||||||
 | 
					      expect(code).toMatch(`declare function __emit__(e: 'foo' | 'bar'): void`)
 | 
				
			||||||
 | 
					      expect(code).toMatch(
 | 
				
			||||||
 | 
					        `declare function __emit__(e: 'baz', id: number): void`
 | 
				
			||||||
 | 
					      )
 | 
				
			||||||
 | 
					      expect(code).toMatch(
 | 
				
			||||||
 | 
					        `emits: ["foo", "bar", "baz"] as unknown as undefined`
 | 
				
			||||||
 | 
					      )
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  describe('errors', () => {
 | 
					  describe('errors', () => {
 | 
				
			||||||
 | 
				
			|||||||
@ -420,7 +420,7 @@ export function compileScriptSetup(
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // check default export to make sure it doesn't reference setup scope
 | 
					  // 4. check default export to make sure it doesn't reference setup scope
 | 
				
			||||||
  // variables
 | 
					  // variables
 | 
				
			||||||
  if (needDefaultExportRefCheck) {
 | 
					  if (needDefaultExportRefCheck) {
 | 
				
			||||||
    checkDefaultExport(
 | 
					    checkDefaultExport(
 | 
				
			||||||
@ -433,7 +433,7 @@ export function compileScriptSetup(
 | 
				
			|||||||
    )
 | 
					    )
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // remove non-script content
 | 
					  // 5. remove non-script content
 | 
				
			||||||
  if (script) {
 | 
					  if (script) {
 | 
				
			||||||
    if (startOffset < scriptStartOffset!) {
 | 
					    if (startOffset < scriptStartOffset!) {
 | 
				
			||||||
      // <script setup> before <script>
 | 
					      // <script setup> before <script>
 | 
				
			||||||
@ -451,8 +451,7 @@ export function compileScriptSetup(
 | 
				
			|||||||
    s.remove(endOffset, source.length)
 | 
					    s.remove(endOffset, source.length)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // wrap setup code with function
 | 
					  // 5. finalize setup argument signature.
 | 
				
			||||||
  // finalize the argument signature.
 | 
					 | 
				
			||||||
  let args = ``
 | 
					  let args = ``
 | 
				
			||||||
  if (isTS) {
 | 
					  if (isTS) {
 | 
				
			||||||
    if (slotsType === '__Slots__') {
 | 
					    if (slotsType === '__Slots__') {
 | 
				
			||||||
@ -480,6 +479,7 @@ export function compileScriptSetup(
 | 
				
			|||||||
    args = hasExplicitSignature ? (scriptSetup.setup as string) : ``
 | 
					    args = hasExplicitSignature ? (scriptSetup.setup as string) : ``
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // 6. wrap setup code with function.
 | 
				
			||||||
  // export the content of <script setup> as a named export, `setup`.
 | 
					  // export the content of <script setup> as a named export, `setup`.
 | 
				
			||||||
  // this allows `import { setup } from '*.vue'` for testing purposes.
 | 
					  // this allows `import { setup } from '*.vue'` for testing purposes.
 | 
				
			||||||
  s.appendLeft(startOffset, `\nexport function setup(${args}) {\n`)
 | 
					  s.appendLeft(startOffset, `\nexport function setup(${args}) {\n`)
 | 
				
			||||||
@ -499,7 +499,7 @@ export function compileScriptSetup(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  s.appendRight(endOffset, `\nreturn ${returned}\n}\n\n`)
 | 
					  s.appendRight(endOffset, `\nreturn ${returned}\n}\n\n`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // finalize default export
 | 
					  // 7. finalize default export
 | 
				
			||||||
  if (isTS) {
 | 
					  if (isTS) {
 | 
				
			||||||
    // for TS, make sure the exported type is still valid type with
 | 
					    // for TS, make sure the exported type is still valid type with
 | 
				
			||||||
    // correct props information
 | 
					    // correct props information
 | 
				
			||||||
@ -520,9 +520,7 @@ export function compileScriptSetup(
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  s.trim()
 | 
					  // 8. expose bindings for template compiler optimization
 | 
				
			||||||
 | 
					 | 
				
			||||||
  // analyze bindings for template compiler optimization
 | 
					 | 
				
			||||||
  if (script) {
 | 
					  if (script) {
 | 
				
			||||||
    Object.assign(bindings, analyzeScriptBindings(script))
 | 
					    Object.assign(bindings, analyzeScriptBindings(script))
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -530,6 +528,7 @@ export function compileScriptSetup(
 | 
				
			|||||||
    bindings[key] = 'setup'
 | 
					    bindings[key] = 'setup'
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  s.trim()
 | 
				
			||||||
  return {
 | 
					  return {
 | 
				
			||||||
    bindings,
 | 
					    bindings,
 | 
				
			||||||
    code: s.toString(),
 | 
					    code: s.toString(),
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user