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