|
|
@ -1,12 +1,7 @@ |
|
|
|
import type { LVal, Node, TSType } from '@babel/types' |
|
|
|
import type { ScriptCompileContext } from './context' |
|
|
|
import { inferRuntimeType } from './resolveType' |
|
|
|
import { |
|
|
|
UNKNOWN_TYPE, |
|
|
|
concatStrings, |
|
|
|
isCallOf, |
|
|
|
toRuntimeTypeString, |
|
|
|
} from './utils' |
|
|
|
import { UNKNOWN_TYPE, isCallOf, toRuntimeTypeString } from './utils' |
|
|
|
import { BindingTypes, unwrapTSNode } from '@vue/compiler-dom' |
|
|
|
|
|
|
|
export const DEFINE_MODEL = 'defineModel' |
|
|
@ -124,44 +119,50 @@ export function genModelProps(ctx: ScriptCompileContext) { |
|
|
|
|
|
|
|
const isProd = !!ctx.options.isProd |
|
|
|
let modelPropsDecl = '' |
|
|
|
for (const [name, { type, options }] of Object.entries(ctx.modelDecls)) { |
|
|
|
for (const [name, { type, options: runtimeOptions }] of Object.entries( |
|
|
|
ctx.modelDecls, |
|
|
|
)) { |
|
|
|
let skipCheck = false |
|
|
|
|
|
|
|
let codegenOptions = `` |
|
|
|
let runtimeTypes = type && inferRuntimeType(ctx, type) |
|
|
|
if (runtimeTypes) { |
|
|
|
const hasBoolean = runtimeTypes.includes('Boolean') |
|
|
|
const hasFunction = runtimeTypes.includes('Function') |
|
|
|
const hasUnknownType = runtimeTypes.includes(UNKNOWN_TYPE) |
|
|
|
|
|
|
|
if (isProd || hasUnknownType) { |
|
|
|
runtimeTypes = runtimeTypes.filter( |
|
|
|
t => |
|
|
|
t === 'Boolean' || |
|
|
|
(hasBoolean && t === 'String') || |
|
|
|
(t === 'Function' && options), |
|
|
|
) |
|
|
|
if (hasUnknownType) { |
|
|
|
if (hasBoolean || hasFunction) { |
|
|
|
runtimeTypes = runtimeTypes.filter(t => t !== UNKNOWN_TYPE) |
|
|
|
skipCheck = true |
|
|
|
} else { |
|
|
|
runtimeTypes = ['null'] |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
skipCheck = !isProd && hasUnknownType && runtimeTypes.length > 0 |
|
|
|
if (!isProd) { |
|
|
|
codegenOptions = |
|
|
|
`type: ${toRuntimeTypeString(runtimeTypes)}` + |
|
|
|
(skipCheck ? ', skipCheck: true' : '') |
|
|
|
} else if (hasBoolean || (runtimeOptions && hasFunction)) { |
|
|
|
// preserve types if contains boolean, or
|
|
|
|
// function w/ runtime options that may contain default
|
|
|
|
codegenOptions = `type: ${toRuntimeTypeString(runtimeTypes)}` |
|
|
|
} else { |
|
|
|
// able to drop types in production
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
let runtimeType = |
|
|
|
(runtimeTypes && |
|
|
|
runtimeTypes.length > 0 && |
|
|
|
toRuntimeTypeString(runtimeTypes)) || |
|
|
|
undefined |
|
|
|
|
|
|
|
const codegenOptions = concatStrings([ |
|
|
|
runtimeType && `type: ${runtimeType}`, |
|
|
|
skipCheck && 'skipCheck: true', |
|
|
|
]) |
|
|
|
|
|
|
|
let decl: string |
|
|
|
if (runtimeType && options) { |
|
|
|
if (codegenOptions && runtimeOptions) { |
|
|
|
decl = ctx.isTS |
|
|
|
? `{ ${codegenOptions}, ...${options} }` |
|
|
|
: `Object.assign({ ${codegenOptions} }, ${options})` |
|
|
|
? `{ ${codegenOptions}, ...${runtimeOptions} }` |
|
|
|
: `Object.assign({ ${codegenOptions} }, ${runtimeOptions})` |
|
|
|
} else if (codegenOptions) { |
|
|
|
decl = `{ ${codegenOptions} }` |
|
|
|
} else if (runtimeOptions) { |
|
|
|
decl = runtimeOptions |
|
|
|
} else { |
|
|
|
decl = options || (runtimeType ? `{ ${codegenOptions} }` : '{}') |
|
|
|
decl = `{}` |
|
|
|
} |
|
|
|
modelPropsDecl += `\n ${JSON.stringify(name)}: ${decl},` |
|
|
|
|
|
|
|