wip: extract runtime props/emits from type declarations
This commit is contained in:
		
							parent
							
								
									608885350b
								
							
						
					
					
						commit
						c0d86070fd
					
				| @ -58,7 +58,6 @@ export function compileScriptSetup( | |||||||
|   const scriptStartOffset = script && script.loc.start.offset |   const scriptStartOffset = script && script.loc.start.offset | ||||||
|   const scriptEndOffset = script && script.loc.end.offset |   const scriptEndOffset = script && script.loc.end.offset | ||||||
| 
 | 
 | ||||||
|   // parse and transform <script setup>
 |  | ||||||
|   const isTS = scriptSetup.lang === 'ts' |   const isTS = scriptSetup.lang === 'ts' | ||||||
|   const plugins: ParserPlugin[] = [ |   const plugins: ParserPlugin[] = [ | ||||||
|     ...(options.parserPlugins || []), |     ...(options.parserPlugins || []), | ||||||
| @ -66,7 +65,7 @@ export function compileScriptSetup( | |||||||
|     ...(isTS ? (['typescript'] as const) : []) |     ...(isTS ? (['typescript'] as const) : []) | ||||||
|   ] |   ] | ||||||
| 
 | 
 | ||||||
|   // process normal <script> first if it exists
 |   // 1. process normal <script> first if it exists
 | ||||||
|   if (script) { |   if (script) { | ||||||
|     // import dedupe between <script> and <script setup>
 |     // import dedupe between <script> and <script setup>
 | ||||||
|     const scriptAST = parse(script.content, { |     const scriptAST = parse(script.content, { | ||||||
| @ -108,7 +107,7 @@ export function compileScriptSetup( | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   // check <script setup="xxx"> function signature
 |   // 2. check <script setup="xxx"> function signature
 | ||||||
|   const hasExplicitSignature = typeof scriptSetup.setup === 'string' |   const hasExplicitSignature = typeof scriptSetup.setup === 'string' | ||||||
|   let propsVar = `$props` |   let propsVar = `$props` | ||||||
|   let emitVar = `$emit` |   let emitVar = `$emit` | ||||||
| @ -124,8 +123,8 @@ export function compileScriptSetup( | |||||||
|   let setupCtxASTNode |   let setupCtxASTNode | ||||||
| 
 | 
 | ||||||
|   // props/emits declared via types
 |   // props/emits declared via types
 | ||||||
|   const typeDeclaredProps: string[] = [] |   const typeDeclaredProps: Set<string> = new Set() | ||||||
|   const typeDeclaredEmits: string[] = [] |   const typeDeclaredEmits: Set<string> = new Set() | ||||||
| 
 | 
 | ||||||
|   if (isTS && hasExplicitSignature) { |   if (isTS && hasExplicitSignature) { | ||||||
|     // <script setup="xxx" lang="ts">
 |     // <script setup="xxx" lang="ts">
 | ||||||
| @ -159,13 +158,11 @@ export function compileScriptSetup( | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   const scriptSetupAST = parse(scriptSetup.content, { |   // 3. parse <script setup> and  walk over top level statements
 | ||||||
|  |   for (const node of parse(scriptSetup.content, { | ||||||
|     plugins, |     plugins, | ||||||
|     sourceType: 'module' |     sourceType: 'module' | ||||||
|   }).program.body |   }).program.body) { | ||||||
| 
 |  | ||||||
|   // walk over top level statements
 |  | ||||||
|   for (const node of scriptSetupAST) { |  | ||||||
|     const start = node.start! + startOffset |     const start = node.start! + startOffset | ||||||
|     let end = node.end! + startOffset |     let end = node.end! + startOffset | ||||||
|     // import or type declarations: move to top
 |     // import or type declarations: move to top
 | ||||||
| @ -436,11 +433,34 @@ export function compileScriptSetup( | |||||||
| 
 | 
 | ||||||
|   s.appendRight(endOffset, `\nreturn ${returned}\n}\n\n`) |   s.appendRight(endOffset, `\nreturn ${returned}\n}\n\n`) | ||||||
| 
 | 
 | ||||||
|  |   // finalize default export
 | ||||||
|  |   if (isTS) { | ||||||
|  |     // for TS, make sure the exported type is still valid type with
 | ||||||
|  |     // correct props information
 | ||||||
|  |     s.prepend(`import { defineComponent as __define__ } from 'vue'\n`) | ||||||
|  |     // we have to use object spread for types to be merged properly
 | ||||||
|  |     // user's TS setting should compile it down to proper targets
 | ||||||
|  |     const def = defaultExport ? `\n  ...__default__,` : `` | ||||||
|  |     const runtimeProps = typeDeclaredProps.size | ||||||
|  |       ? `\n  props: [${Array.from(typeDeclaredProps) | ||||||
|  |           .map(p => JSON.stringify(p)) | ||||||
|  |           .join(', ')}] as unknown as undefined,` | ||||||
|  |       : `` | ||||||
|  |     const runtimeEmits = typeDeclaredEmits.size | ||||||
|  |       ? `\n  emits: [${Array.from(typeDeclaredEmits) | ||||||
|  |           .map(p => JSON.stringify(p)) | ||||||
|  |           .join(', ')}] as unknown as undefined,` | ||||||
|  |       : `` | ||||||
|  |     s.append( | ||||||
|  |       `export default __define__({${def}${runtimeProps}${runtimeEmits}\n  setup\n})` | ||||||
|  |     ) | ||||||
|  |   } else { | ||||||
|     if (defaultExport) { |     if (defaultExport) { | ||||||
|       s.append(`__default__.setup = setup\nexport default __default__`) |       s.append(`__default__.setup = setup\nexport default __default__`) | ||||||
|     } else { |     } else { | ||||||
|       s.append(`export default { setup }`) |       s.append(`export default { setup }`) | ||||||
|     } |     } | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
|   s.trim() |   s.trim() | ||||||
| 
 | 
 | ||||||
| @ -536,17 +556,36 @@ function walkPattern(node: Node, bindings: Record<string, boolean>) { | |||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function extractProps(node: TSTypeLiteral, props: string[]) { | function extractProps(node: TSTypeLiteral, props: Set<string>) { | ||||||
|   // TODO
 |   for (const m of node.members) { | ||||||
|   console.log('gen props', node, props) |     if (m.type === 'TSPropertySignature' && m.key.type === 'Identifier') { | ||||||
|  |       props.add(m.key.name) | ||||||
|  |     } | ||||||
|  |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function extractEmits( | function extractEmits( | ||||||
|   node: TSFunctionType | TSDeclareFunction, |   node: TSFunctionType | TSDeclareFunction, | ||||||
|   emits: string[] |   emits: Set<string> | ||||||
| ) { | ) { | ||||||
|   // TODO
 |   const eventName = | ||||||
|   console.log('gen emits', node, emits) |     node.type === 'TSDeclareFunction' ? node.params[0] : node.parameters[0] | ||||||
|  |   if ( | ||||||
|  |     eventName.type === 'Identifier' && | ||||||
|  |     eventName.typeAnnotation && | ||||||
|  |     eventName.typeAnnotation.type === 'TSTypeAnnotation' | ||||||
|  |   ) { | ||||||
|  |     const typeNode = eventName.typeAnnotation.typeAnnotation | ||||||
|  |     if (typeNode.type === 'TSLiteralType') { | ||||||
|  |       emits.add(String(typeNode.literal.value)) | ||||||
|  |     } else if (typeNode.type === 'TSUnionType') { | ||||||
|  |       for (const t of typeNode.types) { | ||||||
|  |         if (t.type === 'TSLiteralType') { | ||||||
|  |           emits.add(String(t.literal.value)) | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user