| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- import { Identifier, LVal, Node, RestElement } from '@babel/types'
- import { isCallOf } from './utils'
- import { ScriptCompileContext } from './context'
- import { resolveTypeElements, resolveUnionType } from './resolveType'
- export const DEFINE_EMITS = 'defineEmits'
- export function processDefineEmits(
- ctx: ScriptCompileContext,
- node: Node,
- declId?: LVal
- ): boolean {
- if (!isCallOf(node, DEFINE_EMITS)) {
- return false
- }
- if (ctx.hasDefineEmitCall) {
- ctx.error(`duplicate ${DEFINE_EMITS}() call`, node)
- }
- ctx.hasDefineEmitCall = true
- ctx.emitsRuntimeDecl = node.arguments[0]
- if (node.typeParameters) {
- if (ctx.emitsRuntimeDecl) {
- ctx.error(
- `${DEFINE_EMITS}() cannot accept both type and non-type arguments ` +
- `at the same time. Use one or the other.`,
- node
- )
- }
- ctx.emitsTypeDecl = node.typeParameters.params[0]
- }
- if (declId) {
- ctx.emitIdentifier =
- declId.type === 'Identifier' ? declId.name : ctx.getString(declId)
- }
- return true
- }
- export function genRuntimeEmits(ctx: ScriptCompileContext): string | undefined {
- let emitsDecl = ''
- if (ctx.emitsRuntimeDecl) {
- emitsDecl = ctx.getString(ctx.emitsRuntimeDecl).trim()
- } else if (ctx.emitsTypeDecl) {
- const typeDeclaredEmits = extractRuntimeEmits(ctx)
- emitsDecl = typeDeclaredEmits.size
- ? `[${Array.from(typeDeclaredEmits)
- .map(k => JSON.stringify(k))
- .join(', ')}]`
- : ``
- }
- if (ctx.hasDefineModelCall) {
- let modelEmitsDecl = `[${Object.keys(ctx.modelDecls)
- .map(n => JSON.stringify(`update:${n}`))
- .join(', ')}]`
- emitsDecl = emitsDecl
- ? `${ctx.helper('mergeModels')}(${emitsDecl}, ${modelEmitsDecl})`
- : modelEmitsDecl
- }
- return emitsDecl
- }
- function extractRuntimeEmits(ctx: ScriptCompileContext): Set<string> {
- const emits = new Set<string>()
- const node = ctx.emitsTypeDecl!
- if (node.type === 'TSFunctionType') {
- extractEventNames(ctx, node.parameters[0], emits)
- return emits
- }
- const { props, calls } = resolveTypeElements(ctx, node)
- let hasProperty = false
- for (const key in props) {
- emits.add(key)
- hasProperty = true
- }
- if (calls) {
- if (hasProperty) {
- ctx.error(
- `defineEmits() type cannot mixed call signature and property syntax.`,
- node
- )
- }
- for (const call of calls) {
- extractEventNames(ctx, call.parameters[0], emits)
- }
- }
- return emits
- }
- function extractEventNames(
- ctx: ScriptCompileContext,
- eventName: Identifier | RestElement,
- emits: Set<string>
- ) {
- if (
- eventName.type === 'Identifier' &&
- eventName.typeAnnotation &&
- eventName.typeAnnotation.type === 'TSTypeAnnotation'
- ) {
- const types = resolveUnionType(ctx, eventName.typeAnnotation.typeAnnotation)
- for (const type of types) {
- if (type.type === 'TSLiteralType') {
- if (
- type.literal.type !== 'UnaryExpression' &&
- type.literal.type !== 'TemplateLiteral'
- ) {
- emits.add(String(type.literal.value))
- }
- }
- }
- }
- }
|