From 9e77580c0c2f0d977bd0031a1d43cc334769d433 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E6=99=BA=E5=AD=90=20Kevin=20Deng?= Date: Mon, 4 Sep 2023 03:59:11 -0500 Subject: [PATCH] feat(compiler-sfc): expose resolve type-based props and emits (#8874) --- packages/compiler-sfc/src/index.ts | 3 +++ .../compiler-sfc/src/script/defineEmits.ts | 10 ++++--- .../compiler-sfc/src/script/defineProps.ts | 22 ++++++++++------ .../compiler-sfc/src/script/resolveType.ts | 26 +++++++++++++++++-- 4 files changed, 48 insertions(+), 13 deletions(-) diff --git a/packages/compiler-sfc/src/index.ts b/packages/compiler-sfc/src/index.ts index 76b4900d46d..c6ee604146e 100644 --- a/packages/compiler-sfc/src/index.ts +++ b/packages/compiler-sfc/src/index.ts @@ -33,6 +33,8 @@ export { // Internals for type resolution export { invalidateTypeCache, registerTS } from './script/resolveType' +export { extractRuntimeProps } from './script/defineProps' +export { extractRuntimeEmits } from './script/defineEmits' // Types export type { @@ -58,6 +60,7 @@ export type { SFCScriptCompileOptions } from './compileScript' export type { ScriptCompileContext } from './script/context' export type { TypeResolveContext, + SimpleTypeResolveOptions, SimpleTypeResolveContext } from './script/resolveType' export type { diff --git a/packages/compiler-sfc/src/script/defineEmits.ts b/packages/compiler-sfc/src/script/defineEmits.ts index 8bd4cdfe543..b7453076cfe 100644 --- a/packages/compiler-sfc/src/script/defineEmits.ts +++ b/packages/compiler-sfc/src/script/defineEmits.ts @@ -8,7 +8,11 @@ import { } from '@babel/types' import { isCallOf } from './utils' import { ScriptCompileContext } from './context' -import { resolveTypeElements, resolveUnionType } from './resolveType' +import { + TypeResolveContext, + resolveTypeElements, + resolveUnionType +} from './resolveType' export const DEFINE_EMITS = 'defineEmits' @@ -64,7 +68,7 @@ export function genRuntimeEmits(ctx: ScriptCompileContext): string | undefined { return emitsDecl } -function extractRuntimeEmits(ctx: ScriptCompileContext): Set { +export function extractRuntimeEmits(ctx: TypeResolveContext): Set { const emits = new Set() const node = ctx.emitsTypeDecl! @@ -97,7 +101,7 @@ function extractRuntimeEmits(ctx: ScriptCompileContext): Set { } function extractEventNames( - ctx: ScriptCompileContext, + ctx: TypeResolveContext, eventName: ArrayPattern | Identifier | ObjectPattern | RestElement, emits: Set ) { diff --git a/packages/compiler-sfc/src/script/defineProps.ts b/packages/compiler-sfc/src/script/defineProps.ts index 5004e314da1..449ed250d1d 100644 --- a/packages/compiler-sfc/src/script/defineProps.ts +++ b/packages/compiler-sfc/src/script/defineProps.ts @@ -8,7 +8,11 @@ import { } from '@babel/types' import { BindingTypes, isFunctionType } from '@vue/compiler-dom' import { ScriptCompileContext } from './context' -import { inferRuntimeType, resolveTypeElements } from './resolveType' +import { + TypeResolveContext, + inferRuntimeType, + resolveTypeElements +} from './resolveType' import { resolveObjectKey, UNKNOWN_TYPE, @@ -150,7 +154,7 @@ export function genRuntimeProps(ctx: ScriptCompileContext): string | undefined { } } } else if (ctx.propsTypeDecl) { - propsDecls = genRuntimePropsFromTypes(ctx) + propsDecls = extractRuntimeProps(ctx) } const modelsDecls = genModelProps(ctx) @@ -162,7 +166,9 @@ export function genRuntimeProps(ctx: ScriptCompileContext): string | undefined { } } -function genRuntimePropsFromTypes(ctx: ScriptCompileContext) { +export function extractRuntimeProps( + ctx: TypeResolveContext +): string | undefined { // this is only called if propsTypeDecl exists const props = resolveRuntimePropsFromType(ctx, ctx.propsTypeDecl!) if (!props.length) { @@ -175,7 +181,7 @@ function genRuntimePropsFromTypes(ctx: ScriptCompileContext) { for (const prop of props) { propStrings.push(genRuntimePropFromType(ctx, prop, hasStaticDefaults)) // register bindings - if (!(prop.key in ctx.bindingMetadata)) { + if ('bindingMetadata' in ctx && !(prop.key in ctx.bindingMetadata)) { ctx.bindingMetadata[prop.key] = BindingTypes.PROPS } } @@ -193,7 +199,7 @@ function genRuntimePropsFromTypes(ctx: ScriptCompileContext) { } function resolveRuntimePropsFromType( - ctx: ScriptCompileContext, + ctx: TypeResolveContext, node: Node ): PropTypeData[] { const props: PropTypeData[] = [] @@ -222,7 +228,7 @@ function resolveRuntimePropsFromType( } function genRuntimePropFromType( - ctx: ScriptCompileContext, + ctx: TypeResolveContext, { key, required, type, skipCheck }: PropTypeData, hasStaticDefaults: boolean ): string { @@ -284,7 +290,7 @@ function genRuntimePropFromType( * static properties, we can directly generate more optimized default * declarations. Otherwise we will have to fallback to runtime merging. */ -function hasStaticWithDefaults(ctx: ScriptCompileContext) { +function hasStaticWithDefaults(ctx: TypeResolveContext) { return !!( ctx.propsRuntimeDefaults && ctx.propsRuntimeDefaults.type === 'ObjectExpression' && @@ -297,7 +303,7 @@ function hasStaticWithDefaults(ctx: ScriptCompileContext) { } function genDestructuredDefaultValue( - ctx: ScriptCompileContext, + ctx: TypeResolveContext, key: string, inferredType?: string[] ): diff --git a/packages/compiler-sfc/src/script/resolveType.ts b/packages/compiler-sfc/src/script/resolveType.ts index 215081dc0b7..12666341e73 100644 --- a/packages/compiler-sfc/src/script/resolveType.ts +++ b/packages/compiler-sfc/src/script/resolveType.ts @@ -42,6 +42,13 @@ import type TS from 'typescript' import { extname, dirname } from 'path' import { minimatch as isMatch } from 'minimatch' +export type SimpleTypeResolveOptions = Partial< + Pick< + SFCScriptCompileOptions, + 'globalTypeFiles' | 'fs' | 'babelParserPlugins' | 'isProd' + > +> + /** * TypeResolveContext is compatible with ScriptCompileContext * but also allows a simpler version of it with minimal required properties @@ -59,13 +66,28 @@ import { minimatch as isMatch } from 'minimatch' */ export type SimpleTypeResolveContext = Pick< ScriptCompileContext, - // required - 'source' | 'filename' | 'error' | 'options' + // file + | 'source' + | 'filename' + + // utils + | 'error' + | 'helper' + | 'getString' + + // props + | 'propsTypeDecl' + | 'propsRuntimeDefaults' + | 'propsDestructuredBindings' + + // emits + | 'emitsTypeDecl' > & Partial< Pick > & { ast: Statement[] + options: SimpleTypeResolveOptions } export type TypeResolveContext = ScriptCompileContext | SimpleTypeResolveContext