|
|
@@ -10,9 +10,7 @@ import {
|
|
|
SimpleExpressionNode,
|
|
|
isFunctionType,
|
|
|
walkIdentifiers,
|
|
|
- getImportedName,
|
|
|
- unwrapTSNode,
|
|
|
- isCallOf
|
|
|
+ getImportedName
|
|
|
} from '@vue/compiler-dom'
|
|
|
import { DEFAULT_FILENAME, SFCDescriptor, SFCScriptBlock } from './parse'
|
|
|
import { parse as _parse, parseExpression, ParserPlugin } from '@babel/parser'
|
|
|
@@ -36,7 +34,6 @@ import {
|
|
|
TSInterfaceBody,
|
|
|
TSTypeElement,
|
|
|
AwaitExpression,
|
|
|
- ObjectMethod,
|
|
|
LVal,
|
|
|
Expression,
|
|
|
TSEnumDeclaration
|
|
|
@@ -54,13 +51,22 @@ import { rewriteDefaultAST } from './rewriteDefault'
|
|
|
import { createCache } from './cache'
|
|
|
import { shouldTransform, transformAST } from '@vue/reactivity-transform'
|
|
|
import { transformDestructuredProps } from './script/definePropsDestructure'
|
|
|
-import { resolveObjectKey, FromNormalScript } from './script/utils'
|
|
|
import { ScriptCompileContext } from './script/context'
|
|
|
import {
|
|
|
processDefineProps,
|
|
|
DEFINE_PROPS,
|
|
|
- WITH_DEFAULTS
|
|
|
+ WITH_DEFAULTS,
|
|
|
+ extractRuntimeProps
|
|
|
} from './script/defineProps'
|
|
|
+import {
|
|
|
+ resolveObjectKey,
|
|
|
+ FromNormalScript,
|
|
|
+ UNKNOWN_TYPE,
|
|
|
+ isLiteralNode,
|
|
|
+ unwrapTSNode,
|
|
|
+ isCallOf
|
|
|
+} from './script/utils'
|
|
|
+import { genRuntimeProps } from './script/defineProps'
|
|
|
|
|
|
// Special compiler macros
|
|
|
const DEFINE_EMITS = 'defineEmits'
|
|
|
@@ -151,11 +157,6 @@ export type PropsDestructureBindings = Record<
|
|
|
type EmitsDeclType = FromNormalScript<
|
|
|
TSFunctionType | TSTypeLiteral | TSInterfaceBody
|
|
|
>
|
|
|
-interface ModelDecl {
|
|
|
- type: TSType | undefined
|
|
|
- options: string | undefined
|
|
|
- identifier: string | undefined
|
|
|
-}
|
|
|
|
|
|
/**
|
|
|
* Compile `<script setup>`
|
|
|
@@ -279,7 +280,6 @@ export function compileScript(
|
|
|
|
|
|
// metadata that needs to be returned
|
|
|
const bindingMetadata: BindingMetadata = {}
|
|
|
- const helperImports: Set<string> = new Set()
|
|
|
const userImports: Record<string, ImportBinding> = Object.create(null)
|
|
|
const scriptBindings: Record<string, BindingTypes> = Object.create(null)
|
|
|
const setupBindings: Record<string, BindingTypes> = Object.create(null)
|
|
|
@@ -290,14 +290,13 @@ export function compileScript(
|
|
|
let emitsTypeDecl: EmitsDeclType | undefined
|
|
|
let emitIdentifier: string | undefined
|
|
|
let optionsRuntimeDecl: Node | undefined
|
|
|
- let modelDecls: Record<string, ModelDecl> = {}
|
|
|
let hasAwait = false
|
|
|
let hasInlinedSsrRenderFn = false
|
|
|
// props/emits declared via types
|
|
|
- const typeDeclaredProps: Record<string, PropTypeData> = {}
|
|
|
+ // const typeDeclaredProps: Record<string, PropTypeData> = {}
|
|
|
const typeDeclaredEmits: Set<string> = new Set()
|
|
|
// record declared types for runtime props type generation
|
|
|
- const declaredTypes: Record<string, string[]> = {}
|
|
|
+ // const declaredTypes: Record<string, string[]> = {}
|
|
|
|
|
|
// magic-string state
|
|
|
const s = new MagicString(source)
|
|
|
@@ -306,11 +305,6 @@ export function compileScript(
|
|
|
const scriptStartOffset = script && script.loc.start.offset
|
|
|
const scriptEndOffset = script && script.loc.end.offset
|
|
|
|
|
|
- function helper(key: string): string {
|
|
|
- helperImports.add(key)
|
|
|
- return `_${key}`
|
|
|
- }
|
|
|
-
|
|
|
function error(
|
|
|
msg: string,
|
|
|
node: Node,
|
|
|
@@ -435,7 +429,7 @@ export function compileScript(
|
|
|
s.overwrite(
|
|
|
startOffset + node.start!,
|
|
|
startOffset + node.end!,
|
|
|
- `${helper('useSlots')}()`
|
|
|
+ `${ctx.helper('useSlots')}()`
|
|
|
)
|
|
|
}
|
|
|
|
|
|
@@ -461,7 +455,7 @@ export function compileScript(
|
|
|
options = arg0
|
|
|
}
|
|
|
|
|
|
- if (modelDecls[modelName]) {
|
|
|
+ if (ctx.modelDecls[modelName]) {
|
|
|
error(`duplicate model name ${JSON.stringify(modelName)}`, node)
|
|
|
}
|
|
|
|
|
|
@@ -469,7 +463,7 @@ export function compileScript(
|
|
|
? s.slice(startOffset + options.start!, startOffset + options.end!)
|
|
|
: undefined
|
|
|
|
|
|
- modelDecls[modelName] = {
|
|
|
+ ctx.modelDecls[modelName] = {
|
|
|
type,
|
|
|
options: optionsString,
|
|
|
identifier:
|
|
|
@@ -507,7 +501,7 @@ export function compileScript(
|
|
|
s.overwrite(
|
|
|
startOffset + node.start!,
|
|
|
startOffset + node.end!,
|
|
|
- `${helper('useModel')}(__props, ${JSON.stringify(modelName)}${
|
|
|
+ `${ctx.helper('useModel')}(__props, ${JSON.stringify(modelName)}${
|
|
|
runtimeOptions ? `, ${runtimeOptions}` : ``
|
|
|
})`
|
|
|
)
|
|
|
@@ -753,7 +747,7 @@ export function compileScript(
|
|
|
s.overwrite(
|
|
|
node.start! + startOffset,
|
|
|
argumentStart + startOffset,
|
|
|
- `${needSemi ? `;` : ``}(\n ([__temp,__restore] = ${helper(
|
|
|
+ `${needSemi ? `;` : ``}(\n ([__temp,__restore] = ${ctx.helper(
|
|
|
`withAsyncContext`
|
|
|
)}(${containsNestedAwait ? `async ` : ``}() => `
|
|
|
)
|
|
|
@@ -765,242 +759,6 @@ export function compileScript(
|
|
|
)
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * check defaults. If the default object is an object literal with only
|
|
|
- * static properties, we can directly generate more optimized default
|
|
|
- * declarations. Otherwise we will have to fallback to runtime merging.
|
|
|
- */
|
|
|
- function hasStaticWithDefaults() {
|
|
|
- return (
|
|
|
- ctx.propsRuntimeDefaults &&
|
|
|
- ctx.propsRuntimeDefaults.type === 'ObjectExpression' &&
|
|
|
- ctx.propsRuntimeDefaults.properties.every(
|
|
|
- node =>
|
|
|
- node.type !== 'SpreadElement' &&
|
|
|
- (!node.computed || node.key.type.endsWith('Literal'))
|
|
|
- )
|
|
|
- )
|
|
|
- }
|
|
|
-
|
|
|
- function concatStrings(strs: Array<string | null | undefined | false>) {
|
|
|
- return strs.filter((s): s is string => !!s).join(', ')
|
|
|
- }
|
|
|
-
|
|
|
- function genRuntimeProps() {
|
|
|
- function genPropsFromTS() {
|
|
|
- const keys = Object.keys(typeDeclaredProps)
|
|
|
- if (!keys.length) return
|
|
|
-
|
|
|
- const hasStaticDefaults = hasStaticWithDefaults()
|
|
|
- const scriptSetupSource = scriptSetup!.content
|
|
|
- let propsDecls = `{
|
|
|
- ${keys
|
|
|
- .map(key => {
|
|
|
- let defaultString: string | undefined
|
|
|
- const destructured = genDestructuredDefaultValue(
|
|
|
- key,
|
|
|
- typeDeclaredProps[key].type
|
|
|
- )
|
|
|
- if (destructured) {
|
|
|
- defaultString = `default: ${destructured.valueString}${
|
|
|
- destructured.needSkipFactory ? `, skipFactory: true` : ``
|
|
|
- }`
|
|
|
- } else if (hasStaticDefaults) {
|
|
|
- const prop = (
|
|
|
- ctx.propsRuntimeDefaults as ObjectExpression
|
|
|
- ).properties.find(node => {
|
|
|
- if (node.type === 'SpreadElement') return false
|
|
|
- return resolveObjectKey(node.key, node.computed) === key
|
|
|
- }) as ObjectProperty | ObjectMethod
|
|
|
- if (prop) {
|
|
|
- if (prop.type === 'ObjectProperty') {
|
|
|
- // prop has corresponding static default value
|
|
|
- defaultString = `default: ${scriptSetupSource.slice(
|
|
|
- prop.value.start!,
|
|
|
- prop.value.end!
|
|
|
- )}`
|
|
|
- } else {
|
|
|
- defaultString = `${prop.async ? 'async ' : ''}${
|
|
|
- prop.kind !== 'method' ? `${prop.kind} ` : ''
|
|
|
- }default() ${scriptSetupSource.slice(
|
|
|
- prop.body.start!,
|
|
|
- prop.body.end!
|
|
|
- )}`
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- const { type, required, skipCheck } = typeDeclaredProps[key]
|
|
|
- if (!isProd) {
|
|
|
- return `${key}: { ${concatStrings([
|
|
|
- `type: ${toRuntimeTypeString(type)}`,
|
|
|
- `required: ${required}`,
|
|
|
- skipCheck && 'skipCheck: true',
|
|
|
- defaultString
|
|
|
- ])} }`
|
|
|
- } else if (
|
|
|
- type.some(
|
|
|
- el =>
|
|
|
- el === 'Boolean' ||
|
|
|
- ((!hasStaticDefaults || defaultString) && el === 'Function')
|
|
|
- )
|
|
|
- ) {
|
|
|
- // #4783 for boolean, should keep the type
|
|
|
- // #7111 for function, if default value exists or it's not static, should keep it
|
|
|
- // in production
|
|
|
- return `${key}: { ${concatStrings([
|
|
|
- `type: ${toRuntimeTypeString(type)}`,
|
|
|
- defaultString
|
|
|
- ])} }`
|
|
|
- } else {
|
|
|
- // production: checks are useless
|
|
|
- return `${key}: ${defaultString ? `{ ${defaultString} }` : `{}`}`
|
|
|
- }
|
|
|
- })
|
|
|
- .join(',\n ')}\n }`
|
|
|
-
|
|
|
- if (ctx.propsRuntimeDefaults && !hasStaticDefaults) {
|
|
|
- propsDecls = `${helper('mergeDefaults')}(${propsDecls}, ${source.slice(
|
|
|
- ctx.propsRuntimeDefaults.start! + startOffset,
|
|
|
- ctx.propsRuntimeDefaults.end! + startOffset
|
|
|
- )})`
|
|
|
- }
|
|
|
-
|
|
|
- return propsDecls
|
|
|
- }
|
|
|
-
|
|
|
- function genModels() {
|
|
|
- if (!ctx.hasDefineModelCall) return
|
|
|
-
|
|
|
- let modelPropsDecl = ''
|
|
|
- for (const [name, { type, options }] of Object.entries(modelDecls)) {
|
|
|
- let skipCheck = false
|
|
|
-
|
|
|
- let runtimeTypes = type && inferRuntimeType(type, declaredTypes)
|
|
|
- if (runtimeTypes) {
|
|
|
- const hasUnknownType = runtimeTypes.includes(UNKNOWN_TYPE)
|
|
|
-
|
|
|
- runtimeTypes = runtimeTypes.filter(el => {
|
|
|
- if (el === UNKNOWN_TYPE) return false
|
|
|
- return isProd
|
|
|
- ? el === 'Boolean' || (el === 'Function' && options)
|
|
|
- : true
|
|
|
- })
|
|
|
- skipCheck = !isProd && hasUnknownType && runtimeTypes.length > 0
|
|
|
- }
|
|
|
-
|
|
|
- let runtimeType =
|
|
|
- (runtimeTypes &&
|
|
|
- runtimeTypes.length > 0 &&
|
|
|
- toRuntimeTypeString(runtimeTypes)) ||
|
|
|
- undefined
|
|
|
-
|
|
|
- const codegenOptions = concatStrings([
|
|
|
- runtimeType && `type: ${runtimeType}`,
|
|
|
- skipCheck && 'skipCheck: true'
|
|
|
- ])
|
|
|
-
|
|
|
- let decl: string
|
|
|
- if (runtimeType && options) {
|
|
|
- decl = ctx.isTS
|
|
|
- ? `{ ${codegenOptions}, ...${options} }`
|
|
|
- : `Object.assign({ ${codegenOptions} }, ${options})`
|
|
|
- } else {
|
|
|
- decl = options || (runtimeType ? `{ ${codegenOptions} }` : '{}')
|
|
|
- }
|
|
|
- modelPropsDecl += `\n ${JSON.stringify(name)}: ${decl},`
|
|
|
- }
|
|
|
- return `{${modelPropsDecl}\n }`
|
|
|
- }
|
|
|
-
|
|
|
- let propsDecls: undefined | string
|
|
|
- if (ctx.propsRuntimeDecl) {
|
|
|
- propsDecls = scriptSetup!.content
|
|
|
- .slice(ctx.propsRuntimeDecl.start!, ctx.propsRuntimeDecl.end!)
|
|
|
- .trim()
|
|
|
- if (ctx.propsDestructureDecl) {
|
|
|
- const defaults: string[] = []
|
|
|
- for (const key in ctx.propsDestructuredBindings) {
|
|
|
- const d = genDestructuredDefaultValue(key)
|
|
|
- if (d)
|
|
|
- defaults.push(
|
|
|
- `${key}: ${d.valueString}${
|
|
|
- d.needSkipFactory ? `, __skip_${key}: true` : ``
|
|
|
- }`
|
|
|
- )
|
|
|
- }
|
|
|
- if (defaults.length) {
|
|
|
- propsDecls = `${helper(
|
|
|
- `mergeDefaults`
|
|
|
- )}(${propsDecls}, {\n ${defaults.join(',\n ')}\n})`
|
|
|
- }
|
|
|
- }
|
|
|
- } else if (ctx.propsTypeDecl) {
|
|
|
- propsDecls = genPropsFromTS()
|
|
|
- }
|
|
|
-
|
|
|
- const modelsDecls = genModels()
|
|
|
-
|
|
|
- if (propsDecls && modelsDecls) {
|
|
|
- return `${helper('mergeModels')}(${propsDecls}, ${modelsDecls})`
|
|
|
- } else {
|
|
|
- return modelsDecls || propsDecls
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- function genDestructuredDefaultValue(
|
|
|
- key: string,
|
|
|
- inferredType?: string[]
|
|
|
- ):
|
|
|
- | {
|
|
|
- valueString: string
|
|
|
- needSkipFactory: boolean
|
|
|
- }
|
|
|
- | undefined {
|
|
|
- const destructured = ctx.propsDestructuredBindings[key]
|
|
|
- const defaultVal = destructured && destructured.default
|
|
|
- if (defaultVal) {
|
|
|
- const value = scriptSetup!.content.slice(
|
|
|
- defaultVal.start!,
|
|
|
- defaultVal.end!
|
|
|
- )
|
|
|
-
|
|
|
- const unwrapped = unwrapTSNode(defaultVal)
|
|
|
-
|
|
|
- if (
|
|
|
- inferredType &&
|
|
|
- inferredType.length &&
|
|
|
- !inferredType.includes(UNKNOWN_TYPE)
|
|
|
- ) {
|
|
|
- const valueType = inferValueType(unwrapped)
|
|
|
- if (valueType && !inferredType.includes(valueType)) {
|
|
|
- error(
|
|
|
- `Default value of prop "${key}" does not match declared type.`,
|
|
|
- unwrapped
|
|
|
- )
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // If the default value is a function or is an identifier referencing
|
|
|
- // external value, skip factory wrap. This is needed when using
|
|
|
- // destructure w/ runtime declaration since we cannot safely infer
|
|
|
- // whether tje expected runtime prop type is `Function`.
|
|
|
- const needSkipFactory =
|
|
|
- !inferredType &&
|
|
|
- (isFunctionType(unwrapped) || unwrapped.type === 'Identifier')
|
|
|
-
|
|
|
- const needFactoryWrap =
|
|
|
- !needSkipFactory &&
|
|
|
- !isLiteralNode(unwrapped) &&
|
|
|
- !inferredType?.includes('Function')
|
|
|
-
|
|
|
- return {
|
|
|
- valueString: needFactoryWrap ? `() => (${value})` : value,
|
|
|
- needSkipFactory
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
function genRuntimeEmits() {
|
|
|
function genEmitsFromTS() {
|
|
|
return typeDeclaredEmits.size
|
|
|
@@ -1019,41 +777,16 @@ export function compileScript(
|
|
|
emitsDecl = genEmitsFromTS()
|
|
|
}
|
|
|
if (ctx.hasDefineModelCall) {
|
|
|
- let modelEmitsDecl = `[${Object.keys(modelDecls)
|
|
|
+ let modelEmitsDecl = `[${Object.keys(ctx.modelDecls)
|
|
|
.map(n => JSON.stringify(`update:${n}`))
|
|
|
.join(', ')}]`
|
|
|
emitsDecl = emitsDecl
|
|
|
- ? `${helper('mergeModels')}(${emitsDecl}, ${modelEmitsDecl})`
|
|
|
+ ? `${ctx.helper('mergeModels')}(${emitsDecl}, ${modelEmitsDecl})`
|
|
|
: modelEmitsDecl
|
|
|
}
|
|
|
return emitsDecl
|
|
|
}
|
|
|
|
|
|
- // 0. parse both <script> and <script setup> blocks
|
|
|
- // const scriptAst =
|
|
|
- // script &&
|
|
|
- // parse(
|
|
|
- // script.content,
|
|
|
- // {
|
|
|
- // plugins,
|
|
|
- // sourceType: 'module'
|
|
|
- // },
|
|
|
- // scriptStartOffset!
|
|
|
- // )
|
|
|
-
|
|
|
- // const scriptSetupAst = parse(
|
|
|
- // scriptSetup.content,
|
|
|
- // {
|
|
|
- // plugins: [
|
|
|
- // ...plugins,
|
|
|
- // // allow top level await but only inside <script setup>
|
|
|
- // 'topLevelAwait'
|
|
|
- // ],
|
|
|
- // sourceType: 'module'
|
|
|
- // },
|
|
|
- // startOffset
|
|
|
- // )
|
|
|
-
|
|
|
const scriptAst = ctx.scriptAst
|
|
|
const scriptSetupAst = ctx.scriptSetupAst!
|
|
|
|
|
|
@@ -1267,7 +1000,7 @@ export function compileScript(
|
|
|
)
|
|
|
refBindings = rootRefs
|
|
|
for (const h of importedHelpers) {
|
|
|
- helperImports.add(h)
|
|
|
+ ctx.helperImports.add(h)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -1458,7 +1191,7 @@ export function compileScript(
|
|
|
node.exportKind === 'type') ||
|
|
|
(node.type === 'VariableDeclaration' && node.declare)
|
|
|
) {
|
|
|
- recordType(node, declaredTypes)
|
|
|
+ recordType(node, ctx.declaredTypes)
|
|
|
if (node.type !== 'TSEnumDeclaration') {
|
|
|
hoistNode(node)
|
|
|
}
|
|
|
@@ -1493,14 +1226,12 @@ export function compileScript(
|
|
|
)
|
|
|
refBindings = refBindings ? [...refBindings, ...rootRefs] : rootRefs
|
|
|
for (const h of importedHelpers) {
|
|
|
- helperImports.add(h)
|
|
|
+ ctx.helperImports.add(h)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 4. extract runtime props/emits code from setup context type
|
|
|
- if (ctx.propsTypeDecl) {
|
|
|
- extractRuntimeProps(ctx.propsTypeDecl, typeDeclaredProps, declaredTypes)
|
|
|
- }
|
|
|
+ extractRuntimeProps(ctx)
|
|
|
if (emitsTypeDecl) {
|
|
|
extractRuntimeEmits(emitsTypeDecl, typeDeclaredEmits, error)
|
|
|
}
|
|
|
@@ -1541,10 +1272,10 @@ export function compileScript(
|
|
|
bindingMetadata[key] = BindingTypes.PROPS
|
|
|
}
|
|
|
}
|
|
|
- for (const key in typeDeclaredProps) {
|
|
|
+ for (const key in ctx.typeDeclaredProps) {
|
|
|
bindingMetadata[key] = BindingTypes.PROPS
|
|
|
}
|
|
|
- for (const key in modelDecls) {
|
|
|
+ for (const key in ctx.modelDecls) {
|
|
|
bindingMetadata[key] = BindingTypes.PROPS
|
|
|
}
|
|
|
// props aliases
|
|
|
@@ -1592,8 +1323,8 @@ export function compileScript(
|
|
|
// no need to do this when targeting SSR
|
|
|
!(options.inlineTemplate && options.templateOptions?.ssr)
|
|
|
) {
|
|
|
- helperImports.add(CSS_VARS_HELPER)
|
|
|
- helperImports.add('unref')
|
|
|
+ ctx.helperImports.add(CSS_VARS_HELPER)
|
|
|
+ ctx.helperImports.add('unref')
|
|
|
s.prependLeft(
|
|
|
startOffset,
|
|
|
`\n${genCssVarsCode(cssVars, bindingMetadata, scopeId, isProd)}\n`
|
|
|
@@ -1617,7 +1348,7 @@ export function compileScript(
|
|
|
if (ctx.propsDestructureRestId) {
|
|
|
s.prependLeft(
|
|
|
startOffset,
|
|
|
- `\nconst ${ctx.propsDestructureRestId} = ${helper(
|
|
|
+ `\nconst ${ctx.propsDestructureRestId} = ${ctx.helper(
|
|
|
`createPropsRestProxy`
|
|
|
)}(__props, ${JSON.stringify(
|
|
|
Object.keys(ctx.propsDestructuredBindings)
|
|
|
@@ -1734,7 +1465,7 @@ export function compileScript(
|
|
|
// as this may get injected by the render function preamble OR the
|
|
|
// css vars codegen
|
|
|
if (ast && ast.helpers.has(UNREF)) {
|
|
|
- helperImports.delete('unref')
|
|
|
+ ctx.helperImports.delete('unref')
|
|
|
}
|
|
|
returned = code
|
|
|
} else {
|
|
|
@@ -1768,7 +1499,7 @@ export function compileScript(
|
|
|
runtimeOptions += `\n __ssrInlineRender: true,`
|
|
|
}
|
|
|
|
|
|
- const propsDecl = genRuntimeProps()
|
|
|
+ const propsDecl = genRuntimeProps(ctx)
|
|
|
if (propsDecl) runtimeOptions += `\n props: ${propsDecl},`
|
|
|
|
|
|
const emitsDecl = genRuntimeEmits()
|
|
|
@@ -1797,7 +1528,7 @@ export function compileScript(
|
|
|
(definedOptions ? `\n ...${definedOptions},` : '')
|
|
|
s.prependLeft(
|
|
|
startOffset,
|
|
|
- `\n${genDefaultAs} /*#__PURE__*/${helper(
|
|
|
+ `\n${genDefaultAs} /*#__PURE__*/${ctx.helper(
|
|
|
`defineComponent`
|
|
|
)}({${def}${runtimeOptions}\n ${
|
|
|
hasAwait ? `async ` : ``
|
|
|
@@ -1827,9 +1558,9 @@ export function compileScript(
|
|
|
}
|
|
|
|
|
|
// 12. finalize Vue helper imports
|
|
|
- if (helperImports.size > 0) {
|
|
|
+ if (ctx.helperImports.size > 0) {
|
|
|
s.prepend(
|
|
|
- `import { ${[...helperImports]
|
|
|
+ `import { ${[...ctx.helperImports]
|
|
|
.map(h => `${h} as _${h}`)
|
|
|
.join(', ')} } from 'vue'\n`
|
|
|
)
|
|
|
@@ -2028,13 +1759,6 @@ function walkPattern(
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-interface PropTypeData {
|
|
|
- key: string
|
|
|
- type: string[]
|
|
|
- required: boolean
|
|
|
- skipCheck: boolean
|
|
|
-}
|
|
|
-
|
|
|
function recordType(node: Node, declaredTypes: Record<string, string[]>) {
|
|
|
if (node.type === 'TSInterfaceDeclaration') {
|
|
|
declaredTypes[node.id.name] = [`Object`]
|
|
|
@@ -2050,45 +1774,6 @@ function recordType(node: Node, declaredTypes: Record<string, string[]>) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-function extractRuntimeProps(
|
|
|
- node: TSTypeLiteral | TSInterfaceBody,
|
|
|
- props: Record<string, PropTypeData>,
|
|
|
- declaredTypes: Record<string, string[]>
|
|
|
-) {
|
|
|
- const members = node.type === 'TSTypeLiteral' ? node.members : node.body
|
|
|
- for (const m of members) {
|
|
|
- if (
|
|
|
- (m.type === 'TSPropertySignature' || m.type === 'TSMethodSignature') &&
|
|
|
- m.key.type === 'Identifier'
|
|
|
- ) {
|
|
|
- let type: string[] | undefined
|
|
|
- let skipCheck = false
|
|
|
- if (m.type === 'TSMethodSignature') {
|
|
|
- type = ['Function']
|
|
|
- } else if (m.typeAnnotation) {
|
|
|
- type = inferRuntimeType(m.typeAnnotation.typeAnnotation, declaredTypes)
|
|
|
- // skip check for result containing unknown types
|
|
|
- if (type.includes(UNKNOWN_TYPE)) {
|
|
|
- if (type.includes('Boolean') || type.includes('Function')) {
|
|
|
- type = type.filter(t => t !== UNKNOWN_TYPE)
|
|
|
- skipCheck = true
|
|
|
- } else {
|
|
|
- type = ['null']
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- props[m.key.name] = {
|
|
|
- key: m.key.name,
|
|
|
- required: !m.optional,
|
|
|
- type: type || [`null`],
|
|
|
- skipCheck
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-const UNKNOWN_TYPE = 'Unknown'
|
|
|
-
|
|
|
function inferRuntimeType(
|
|
|
node: TSType,
|
|
|
declaredTypes: Record<string, string[]>
|
|
|
@@ -2239,10 +1924,6 @@ function flattenTypes(
|
|
|
]
|
|
|
}
|
|
|
|
|
|
-function toRuntimeTypeString(types: string[]) {
|
|
|
- return types.length > 1 ? `[${types.join(', ')}]` : types[0]
|
|
|
-}
|
|
|
-
|
|
|
function inferEnumType(node: TSEnumDeclaration): string[] {
|
|
|
const types = new Set<string>()
|
|
|
for (const m of node.members) {
|
|
|
@@ -2260,27 +1941,6 @@ function inferEnumType(node: TSEnumDeclaration): string[] {
|
|
|
return types.size ? [...types] : ['Number']
|
|
|
}
|
|
|
|
|
|
-// non-comprehensive, best-effort type infernece for a runtime value
|
|
|
-// this is used to catch default value / type declaration mismatches
|
|
|
-// when using props destructure.
|
|
|
-function inferValueType(node: Node): string | undefined {
|
|
|
- switch (node.type) {
|
|
|
- case 'StringLiteral':
|
|
|
- return 'String'
|
|
|
- case 'NumericLiteral':
|
|
|
- return 'Number'
|
|
|
- case 'BooleanLiteral':
|
|
|
- return 'Boolean'
|
|
|
- case 'ObjectExpression':
|
|
|
- return 'Object'
|
|
|
- case 'ArrayExpression':
|
|
|
- return 'Array'
|
|
|
- case 'FunctionExpression':
|
|
|
- case 'ArrowFunctionExpression':
|
|
|
- return 'Function'
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
function extractRuntimeEmits(
|
|
|
node: TSFunctionType | TSTypeLiteral | TSInterfaceBody,
|
|
|
emits: Set<string>,
|
|
|
@@ -2414,10 +2074,6 @@ function isStaticNode(node: Node): boolean {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-function isLiteralNode(node: Node) {
|
|
|
- return node.type.endsWith('Literal')
|
|
|
-}
|
|
|
-
|
|
|
/**
|
|
|
* Analyze bindings in normal `<script>`
|
|
|
* Note that `compileScriptSetup` already analyzes bindings as part of its
|