diff --git a/packages/compiler-core/__tests__/transforms/transformExpressions.spec.ts b/packages/compiler-core/__tests__/transforms/transformExpressions.spec.ts index 2f1e6eb6412..9fe9dff2890 100644 --- a/packages/compiler-core/__tests__/transforms/transformExpressions.spec.ts +++ b/packages/compiler-core/__tests__/transforms/transformExpressions.spec.ts @@ -592,7 +592,7 @@ describe('compiler: expression transform', () => { [ 'pipelineOperator', { - proposal: 'minimal', + proposal: 'fsharp', }, ], ], diff --git a/packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap b/packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap index 2acac64b0fb..f45632fc896 100644 --- a/packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap +++ b/packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap @@ -1358,20 +1358,6 @@ _sfc_.setup = __setup__ " `; -exports[`SFC genDefaultAs > parser plugins > import attributes (user override for deprecated syntax) 1`] = ` -"import { foo } from './foo.js' assert { type: 'foobar' } - -export default { - setup(__props, { expose: __expose }) { - __expose(); - - -return { get foo() { return foo } } -} - -}" -`; - exports[`SFC genDefaultAs > parser plugins > import attributes 1`] = ` "import { foo } from './foo.js' with { type: 'foobar' } diff --git a/packages/compiler-sfc/__tests__/compileScript.spec.ts b/packages/compiler-sfc/__tests__/compileScript.spec.ts index b69bbca2e16..13d875a3c46 100644 --- a/packages/compiler-sfc/__tests__/compileScript.spec.ts +++ b/packages/compiler-sfc/__tests__/compileScript.spec.ts @@ -1510,22 +1510,6 @@ describe('SFC genDefaultAs', () => { `), ).toThrow() }) - - test('import attributes (user override for deprecated syntax)', () => { - const { content } = compile( - ` - - `, - { - babelParserPlugins: [ - ['importAttributes', { deprecatedAssertSyntax: true }], - ], - }, - ) - assertCode(content) - }) }) }) diff --git a/packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts b/packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts index eff2f01b981..d17c21befb5 100644 --- a/packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts +++ b/packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts @@ -1653,7 +1653,7 @@ function resolve( s.expression.type === 'CallExpression' && (s.expression.callee as Identifier).name === 'defineProps' ) { - target = s.expression.typeParameters!.params[0] + target = s.expression.typeArguments!.params[0] } } const raw = resolveTypeElements(ctx, target) diff --git a/packages/compiler-sfc/__tests__/utils.ts b/packages/compiler-sfc/__tests__/utils.ts index b5cfc9606d5..8452b75f792 100644 --- a/packages/compiler-sfc/__tests__/utils.ts +++ b/packages/compiler-sfc/__tests__/utils.ts @@ -29,10 +29,7 @@ export function assertCode(code: string): void { try { babelParse(code, { sourceType: 'module', - plugins: [ - 'typescript', - ['importAttributes', { deprecatedAssertSyntax: true }], - ], + plugins: ['typescript'], }) } catch (e: any) { console.log(code) diff --git a/packages/compiler-sfc/src/compileScript.ts b/packages/compiler-sfc/src/compileScript.ts index de7deded7e5..8b41886af57 100644 --- a/packages/compiler-sfc/src/compileScript.ts +++ b/packages/compiler-sfc/src/compileScript.ts @@ -1161,7 +1161,7 @@ function walkDeclaration( } } } else if (node.type === 'TSEnumDeclaration') { - isAllLiteral = node.members.every( + isAllLiteral = node.body.members.every( member => !member.initializer || isStaticNode(member.initializer), ) bindings[node.id!.name] = isAllLiteral diff --git a/packages/compiler-sfc/src/script/context.ts b/packages/compiler-sfc/src/script/context.ts index 3d6a129161f..8127103d7b9 100644 --- a/packages/compiler-sfc/src/script/context.ts +++ b/packages/compiler-sfc/src/script/context.ts @@ -1,6 +1,6 @@ import type { CallExpression, Node, ObjectPattern, Program } from '@babel/types' import type { SFCDescriptor } from '../parse' -import { generateCodeFrame, isArray } from '@vue/shared' +import { generateCodeFrame } from '@vue/shared' import { type ParserPlugin, parse as babelParse } from '@babel/parser' import type { ImportBinding, SFCScriptCompileOptions } from '../compileScript' import type { PropsDestructureBindings } from './defineProps' @@ -170,17 +170,6 @@ export function resolveParserPlugins( dts = false, ): ParserPlugin[] { const plugins: ParserPlugin[] = [] - if ( - !userPlugins || - !userPlugins.some( - p => - p === 'importAssertions' || - p === 'importAttributes' || - (isArray(p) && p[0] === 'importAttributes'), - ) - ) { - plugins.push('importAttributes') - } if (lang === 'jsx' || lang === 'tsx' || lang === 'mtsx') { plugins.push('jsx') } else if (userPlugins) { @@ -189,7 +178,7 @@ export function resolveParserPlugins( userPlugins = userPlugins.filter(p => p !== 'jsx') } if (lang === 'ts' || lang === 'mts' || lang === 'tsx' || lang === 'mtsx') { - plugins.push(['typescript', { dts }], 'explicitResourceManagement') + plugins.push(['typescript', { dts }]) if (!userPlugins || !userPlugins.includes('decorators')) { plugins.push('decorators-legacy') } diff --git a/packages/compiler-sfc/src/script/defineEmits.ts b/packages/compiler-sfc/src/script/defineEmits.ts index e4e6bdabf36..20e196d4026 100644 --- a/packages/compiler-sfc/src/script/defineEmits.ts +++ b/packages/compiler-sfc/src/script/defineEmits.ts @@ -29,7 +29,7 @@ export function processDefineEmits( } ctx.hasDefineEmitCall = true ctx.emitsRuntimeDecl = node.arguments[0] - if (node.typeParameters) { + if (node.typeArguments) { if (ctx.emitsRuntimeDecl) { ctx.error( `${DEFINE_EMITS}() cannot accept both type and non-type arguments ` + @@ -37,7 +37,7 @@ export function processDefineEmits( node, ) } - ctx.emitsTypeDecl = node.typeParameters.params[0] + ctx.emitsTypeDecl = node.typeArguments.params[0] } ctx.emitDecl = declId @@ -75,7 +75,7 @@ export function extractRuntimeEmits(ctx: TypeResolveContext): Set { const node = ctx.emitsTypeDecl! if (node.type === 'TSFunctionType') { - extractEventNames(ctx, node.parameters[0], emits) + extractEventNames(ctx, node.params[0], emits) return emits } @@ -95,7 +95,7 @@ export function extractRuntimeEmits(ctx: TypeResolveContext): Set { ) } for (const call of calls) { - extractEventNames(ctx, call.parameters[0], emits) + extractEventNames(ctx, call.params[0], emits) } } diff --git a/packages/compiler-sfc/src/script/defineModel.ts b/packages/compiler-sfc/src/script/defineModel.ts index a0b5e11fe4f..70de203d9c6 100644 --- a/packages/compiler-sfc/src/script/defineModel.ts +++ b/packages/compiler-sfc/src/script/defineModel.ts @@ -24,8 +24,9 @@ export function processDefineModel( ctx.hasDefineModelCall = true - const type = - (node.typeParameters && node.typeParameters.params[0]) || undefined + const type = (node.typeArguments && node.typeArguments.params[0]) as + | TSType + | undefined let modelName: string let options: Node | undefined const arg0 = node.arguments[0] && unwrapTSNode(node.arguments[0]) diff --git a/packages/compiler-sfc/src/script/defineOptions.ts b/packages/compiler-sfc/src/script/defineOptions.ts index 0ab6de3080b..14448a2e499 100644 --- a/packages/compiler-sfc/src/script/defineOptions.ts +++ b/packages/compiler-sfc/src/script/defineOptions.ts @@ -19,7 +19,7 @@ export function processDefineOptions( if (ctx.hasDefineOptionsCall) { ctx.error(`duplicate ${DEFINE_OPTIONS}() call`, node) } - if (node.typeParameters) { + if (node.typeArguments) { ctx.error(`${DEFINE_OPTIONS}() cannot accept type arguments`, node) } if (!node.arguments[0]) return true diff --git a/packages/compiler-sfc/src/script/defineProps.ts b/packages/compiler-sfc/src/script/defineProps.ts index 9a4880a1a54..5b1daa83349 100644 --- a/packages/compiler-sfc/src/script/defineProps.ts +++ b/packages/compiler-sfc/src/script/defineProps.ts @@ -70,7 +70,7 @@ export function processDefineProps( } // call has type parameters - infer runtime types from it - if (node.typeParameters) { + if (node.typeArguments) { if (ctx.propsRuntimeDecl) { ctx.error( `${DEFINE_PROPS}() cannot accept both type and non-type arguments ` + @@ -78,7 +78,7 @@ export function processDefineProps( node, ) } - ctx.propsTypeDecl = node.typeParameters.params[0] + ctx.propsTypeDecl = node.typeArguments.params[0] } // handle props destructure diff --git a/packages/compiler-sfc/src/script/resolveType.ts b/packages/compiler-sfc/src/script/resolveType.ts index 54b93b3fe7a..43051b24d67 100644 --- a/packages/compiler-sfc/src/script/resolveType.ts +++ b/packages/compiler-sfc/src/script/resolveType.ts @@ -3,19 +3,22 @@ import type { Identifier, Node, Statement, + StringLiteral, TSCallSignatureDeclaration, + TSEntityName, TSEnumDeclaration, - TSExpressionWithTypeArguments, TSFunctionType, TSImportType, TSIndexedAccessType, TSInterfaceDeclaration, + TSInterfaceHeritage, TSMappedType, TSMethodSignature, TSModuleBlock, TSModuleDeclaration, TSPropertySignature, TSQualifiedName, + TSTemplateLiteralType, TSType, TSTypeAnnotation, TSTypeElement, @@ -203,19 +206,19 @@ function innerResolveTypeElements( 'TSUnionType', ) } - case 'TSExpressionWithTypeArguments': // referenced by interface extends + case 'TSInterfaceHeritage': // referenced by interface extends case 'TSTypeReference': { const typeName = getReferenceName(node) if ( (typeName === 'ExtractPropTypes' || typeName === 'ExtractPublicPropTypes') && - node.typeParameters && + node.typeArguments && scope.imports[typeName]?.source === 'vue' ) { return resolveExtractPropTypes( resolveTypeElements( ctx, - node.typeParameters.params[0], + node.typeArguments.params[0], scope, typeParameters, ), @@ -229,13 +232,13 @@ function innerResolveTypeElements( (resolved.type === 'TSTypeAliasDeclaration' || resolved.type === 'TSInterfaceDeclaration') && resolved.typeParameters && - node.typeParameters + node.typeArguments ) { typeParams = Object.create(null) resolved.typeParameters.params.forEach((p, i) => { - let param = typeParameters && typeParameters[p.name] - if (!param) param = node.typeParameters!.params[i] - typeParams![p.name] = param + let param = typeParameters && typeParameters[p.name.name] + if (!param) param = node.typeArguments!.params[i] + typeParams![p.name.name] = param }) } return resolveTypeElements( @@ -265,11 +268,11 @@ function innerResolveTypeElements( scope, typeParameters, ) - } else if (typeName === 'ReturnType' && node.typeParameters) { + } else if (typeName === 'ReturnType' && node.typeArguments) { // limited support, only reference types const ret = resolveReturnType( ctx, - node.typeParameters.params[0], + node.typeArguments.params[0], scope, ) if (ret) { @@ -286,13 +289,13 @@ function innerResolveTypeElements( } case 'TSImportType': { if ( - getId(node.argument) === 'vue' && + getId(node.argument.literal) === 'vue' && node.qualifier?.type === 'Identifier' && node.qualifier.name === 'ExtractPropTypes' && - node.typeParameters + node.typeArguments ) { return resolveExtractPropTypes( - resolveTypeElements(ctx, node.typeParameters.params[0], scope), + resolveTypeElements(ctx, node.typeArguments.params[0], scope), scope, ) } @@ -300,7 +303,7 @@ function innerResolveTypeElements( ctx, node.argument, scope, - node.argument.value, + (node.argument.literal as StringLiteral).value, ) const resolved = resolveTypeReference(ctx, node, sourceScope) if (resolved) { @@ -457,12 +460,12 @@ function resolveMappedType( const res: ResolvedElements = { props: {} } let keys: string[] if (node.nameType) { - const { name, constraint } = node.typeParameter + const { key, constraint } = node scope = createChildScope(scope) - Object.assign(scope.types, { ...typeParameters, [name]: constraint }) + Object.assign(scope.types, { ...typeParameters, [key.name]: constraint }) keys = resolveStringType(ctx, node.nameType, scope) } else { - keys = resolveStringType(ctx, node.typeParameter.constraint!, scope) + keys = resolveStringType(ctx, node.constraint!, scope) } for (const key of keys) { res.props[key] = createProperty( @@ -499,7 +502,11 @@ function resolveIndexType( resolved = resolveTypeElements(ctx, objectType, scope) } for (const key of keys) { - const targetType = resolved.props[key]?.typeAnnotation?.typeAnnotation + const prop = resolved.props[key] + const targetType = + prop?.type === 'TSMethodSignature' + ? prop?.returnType?.typeAnnotation + : prop?.typeAnnotation?.typeAnnotation if (targetType) { ;(targetType as TSType & MaybeWithScope)._ownerScope = resolved.props[key]._ownerScope @@ -526,8 +533,8 @@ function resolveArrayElementType( } if (node.type === 'TSTypeReference') { // Array - if (getReferenceName(node) === 'Array' && node.typeParameters) { - return node.typeParameters.params + if (getReferenceName(node) === 'Array' && node.typeArguments) { + return node.typeArguments.params } else { const resolved = resolveTypeReference(ctx, node, scope) if (resolved) { @@ -557,9 +564,10 @@ function resolveStringType( return node.types .map(t => resolveStringType(ctx, t, scope, typeParameters)) .flat() - case 'TemplateLiteral': { + case 'TemplateLiteral': return resolveTemplateKeys(ctx, node, scope) - } + case 'TSTemplateLiteralType': + return resolveTSTemplateKeys(ctx, node, scope) case 'TSTypeReference': { const resolved = resolveTypeReference(ctx, node, scope) if (resolved) { @@ -578,7 +586,7 @@ function resolveStringType( const getParam = (index = 0) => resolveStringType( ctx, - node.typeParameters!.params[index], + node.typeArguments!.params[index], scope, typeParameters, ) @@ -643,6 +651,39 @@ function resolveTemplateKeys( return res } +function resolveTSTemplateKeys( + ctx: TypeResolveContext, + node: TSTemplateLiteralType, + scope: TypeScope, +): string[] { + if (!node.types.length) { + return [node.quasis[0].value.raw] + } + + const res: string[] = [] + const e = node.types[0] + const q = node.quasis[0] + const leading = q ? q.value.raw : `` + const resolved = resolveStringType(ctx, e, scope) + const restResolved = resolveTSTemplateKeys( + ctx, + { + ...node, + types: node.types.slice(1), + quasis: q ? node.quasis.slice(1) : node.quasis, + }, + scope, + ) + + for (const r of resolved) { + for (const rr of restResolved) { + res.push(leading + r + rr) + } + } + + return res +} + const SupportedBuiltinsSet = new Set([ 'Partial', 'Required', @@ -655,14 +696,14 @@ type GetSetType = T extends Set ? V : never function resolveBuiltin( ctx: TypeResolveContext, - node: TSTypeReference | TSExpressionWithTypeArguments, + node: TSTypeReference | TSInterfaceHeritage, name: GetSetType, scope: TypeScope, typeParameters?: Record, ): ResolvedElements { const t = resolveTypeElements( ctx, - node.typeParameters!.params[0], + node.typeArguments!.params[0], scope, typeParameters, ) @@ -686,7 +727,7 @@ function resolveBuiltin( case 'Pick': { const picked = resolveStringType( ctx, - node.typeParameters!.params[1], + node.typeArguments!.params[1], scope, typeParameters, ) @@ -699,7 +740,7 @@ function resolveBuiltin( case 'Omit': const omitted = resolveStringType( ctx, - node.typeParameters!.params[1], + node.typeArguments!.params[1], scope, typeParameters, ) @@ -715,7 +756,7 @@ function resolveBuiltin( type ReferenceTypes = | TSTypeReference - | TSExpressionWithTypeArguments + | TSInterfaceHeritage | TSImportType | TSTypeQuery @@ -802,7 +843,7 @@ function getReferenceName(node: ReferenceTypes): string | string[] { const ref = node.type === 'TSTypeReference' ? node.typeName - : node.type === 'TSExpressionWithTypeArguments' + : node.type === 'TSInterfaceHeritage' ? node.expression : node.type === 'TSImportType' ? node.qualifier @@ -820,10 +861,47 @@ function qualifiedNameToPath(node: Identifier | TSQualifiedName): string[] { if (node.type === 'Identifier') { return [node.name] } else { - return [...qualifiedNameToPath(node.left), node.right.name] + return [ + ...qualifiedNameToPath(node.left as Identifier | TSQualifiedName), + node.right.name, + ] + } +} + +function pathToQualifiedName(path: string[]): TSQualifiedName | Identifier { + if (path.length === 1) { + return { + type: 'Identifier', + name: path[0], + } + } else { + return { + type: 'TSQualifiedName', + left: pathToQualifiedName(path.slice(0, -1)), + right: { + type: 'Identifier', + name: path[path.length - 1], + }, + } } } +function buildTSModuleDeclarationWithoutFirstId(node: TSModuleDeclaration) { + const path = + node.id.type === 'StringLiteral' + ? [node.id.value] + : qualifiedNameToPath(node.id as TSQualifiedName | Identifier) + return { + type: 'TSModuleDeclaration', + kind: 'module', + id: pathToQualifiedName(path.slice(1)), + body: { + type: 'TSModuleBlock', + body: [...node.body.body], + }, + } as TSModuleDeclaration +} + function resolveGlobalScope(ctx: TypeResolveContext): TypeScope[] | undefined { if (ctx.options.globalTypeFiles) { const fs = resolveFS(ctx) @@ -1261,10 +1339,12 @@ function moduleDeclToScope( const scope = createChildScope(parentScope) - if (node.body.type === 'TSModuleDeclaration') { - const decl = node.body as TSModuleDeclaration & WithScope + if (node.id.type === 'TSQualifiedName') { + const decl = buildTSModuleDeclarationWithoutFirstId( + node, + ) as TSModuleDeclaration & WithScope decl._ownerScope = scope - const id = getId(decl.id) + const id = qualifiedNameToPath(node.id)[1] scope.types[id] = scope.exportedTypes[id] = decl } else { recordTypes(ctx, node.body.body, scope) @@ -1302,7 +1382,10 @@ function recordTypes( if ((stmt as any).declare) { recordType(stmt, types, declares) } - } else if (stmt.type === 'TSModuleDeclaration' && stmt.global) { + } else if ( + stmt.type === 'TSModuleDeclaration' && + stmt.kind === 'global' + ) { for (const s of (stmt.body as TSModuleBlock).body) { if (s.type === 'ExportNamedDeclaration' && s.declaration) { // Handle export declarations inside declare global @@ -1416,7 +1499,7 @@ function recordType( if (node.type === 'TSInterfaceDeclaration') { ;(existing as typeof node).body.body.push(...node.body.body) } else { - ;(existing as typeof node).members.push(...node.members) + ;(existing as typeof node).body.members.push(...node.body.members) } } else { types[id] = node @@ -1447,33 +1530,59 @@ function recordType( } } -function mergeNamespaces(to: TSModuleDeclaration, from: TSModuleDeclaration) { - const toBody = to.body - const fromBody = from.body - if (toBody.type === 'TSModuleDeclaration') { - if (fromBody.type === 'TSModuleDeclaration') { +function mergeNamespaces( + to: TSModuleDeclaration, + from: TSModuleDeclaration, + toId: TSEntityName | StringLiteral = to.id, + fromId: TSEntityName | StringLiteral = from.id, +) { + if (toId.type === 'TSQualifiedName') { + if (fromId.type === 'TSQualifiedName') { // both decl - mergeNamespaces(toBody, fromBody) + mergeNamespaces( + to, + from, + pathToQualifiedName(qualifiedNameToPath(toId).slice(1)), + pathToQualifiedName(qualifiedNameToPath(fromId).slice(1)), + ) } else { // to: decl -> from: block - fromBody.body.push({ + from.body.body.push({ type: 'ExportNamedDeclaration', - declaration: toBody, + declaration: { + type: 'TSModuleDeclaration', + kind: 'module', + id: pathToQualifiedName(qualifiedNameToPath(toId).slice(1)), + body: { + type: 'TSModuleBlock', + body: [...to.body.body], + }, + }, exportKind: 'type', specifiers: [], }) } - } else if (fromBody.type === 'TSModuleDeclaration') { + } else if (from.id.type === 'TSQualifiedName') { // to: block <- from: decl - toBody.body.push({ + to.body.body.push({ type: 'ExportNamedDeclaration', - declaration: fromBody, + declaration: { + type: 'TSModuleDeclaration', + kind: 'module', + id: pathToQualifiedName( + qualifiedNameToPath(fromId as Identifier | TSQualifiedName).slice(1), + ), + body: { + type: 'TSModuleBlock', + body: [...from.body.body], + }, + }, exportKind: 'type', specifiers: [], }) } else { // both block - toBody.body.push(...fromBody.body) + to.body.body.push(...from.body.body) } } @@ -1549,8 +1658,9 @@ export function inferRuntimeType( ) { types.add('Number') } else if (m.type === 'TSIndexSignature') { - const annotation = m.parameters[0].typeAnnotation - if (annotation && annotation.type !== 'Noop') { + const annotation = m.parameters[0] + .typeAnnotation as TSTypeAnnotation + if (annotation) { const type = inferRuntimeType( ctx, annotation.typeAnnotation, @@ -1617,11 +1727,11 @@ export function inferRuntimeType( return ['Function'] } - if (node.typeParameters) { + if (node.typeArguments) { const typeParams: Record = Object.create(null) if (resolved.typeParameters) { resolved.typeParameters.params.forEach((p, i) => { - typeParams![p.name] = node.typeParameters!.params[i] + typeParams![p.name.name] = node.typeArguments!.params[i] }) } return inferRuntimeType( @@ -1661,10 +1771,10 @@ export function inferRuntimeType( case 'Partial': case 'Required': case 'Readonly': - if (node.typeParameters && node.typeParameters.params[0]) { + if (node.typeArguments && node.typeArguments.params[0]) { return inferRuntimeType( ctx, - node.typeParameters.params[0], + node.typeArguments.params[0], scope, true, ) @@ -1672,10 +1782,10 @@ export function inferRuntimeType( break case 'Pick': case 'Extract': - if (node.typeParameters && node.typeParameters.params[1]) { + if (node.typeArguments && node.typeArguments.params[1]) { return inferRuntimeType( ctx, - node.typeParameters.params[1], + node.typeArguments.params[1], scope, ) } @@ -1740,29 +1850,29 @@ export function inferRuntimeType( return ['Set'] case 'NonNullable': - if (node.typeParameters && node.typeParameters.params[0]) { + if (node.typeArguments && node.typeArguments.params[0]) { return inferRuntimeType( ctx, - node.typeParameters.params[0], + node.typeArguments.params[0], scope, ).filter(t => t !== 'null') } break case 'Extract': - if (node.typeParameters && node.typeParameters.params[1]) { + if (node.typeArguments && node.typeArguments.params[1]) { return inferRuntimeType( ctx, - node.typeParameters.params[1], + node.typeArguments.params[1], scope, ) } break case 'Exclude': case 'OmitThisParameter': - if (node.typeParameters && node.typeParameters.params[0]) { + if (node.typeArguments && node.typeArguments.params[0]) { return inferRuntimeType( ctx, - node.typeParameters.params[0], + node.typeArguments.params[0], scope, ) } @@ -1790,15 +1900,13 @@ export function inferRuntimeType( } case 'TSMappedType': { // only support { [K in keyof T]: T[K] } - const { typeAnnotation, typeParameter } = node + const { typeAnnotation, key, constraint } = node if ( typeAnnotation && typeAnnotation.type === 'TSIndexedAccessType' && - typeParameter && - typeParameter.constraint && + constraint && typeParameters ) { - const constraint = typeParameter.constraint if ( constraint.type === 'TSTypeOperator' && constraint.operator === 'keyof' && @@ -1817,7 +1925,7 @@ export function inferRuntimeType( index && index.type === 'TSTypeReference' && index.typeName.type === 'Identifier' && - index.typeName.name === typeParameter.name + index.typeName.name === key.name ) { const targetType = typeParameters[typeName] if (targetType) { @@ -1849,7 +1957,7 @@ export function inferRuntimeType( ctx, node.argument, scope, - node.argument.value, + (node.argument.literal as StringLiteral).value, ) const resolved = resolveTypeReference(ctx, node, sourceScope) if (resolved) { @@ -1916,7 +2024,7 @@ function flattenTypes( function inferEnumType(node: TSEnumDeclaration): string[] { const types = new Set() - for (const m of node.members) { + for (const m of node.body.members) { if (m.initializer) { switch (m.initializer.type) { case 'StringLiteral': @@ -1944,7 +2052,9 @@ function resolveExtractPropTypes( const raw = props[key] res.props[key] = reverseInferType( raw.key, - raw.typeAnnotation!.typeAnnotation, + raw.type === 'TSMethodSignature' + ? raw.returnType!.typeAnnotation + : raw.typeAnnotation!.typeAnnotation, scope, ) } @@ -1982,17 +2092,17 @@ function reverseInferType( scope, optional, ) - } else if (node.typeName.name === 'PropType' && node.typeParameters) { + } else if (node.typeName.name === 'PropType' && node.typeArguments) { // PropType<{}> - return createProperty(key, node.typeParameters.params[0], scope, optional) + return createProperty(key, node.typeArguments.params[0], scope, optional) } } if ( (node.type === 'TSTypeReference' || node.type === 'TSImportType') && - node.typeParameters + node.typeArguments ) { // try if we can catch Foo.Bar - for (const t of node.typeParameters.params) { + for (const t of node.typeArguments.params) { const inferred = reverseInferType(key, t, scope, optional) if (inferred) return inferred } @@ -2032,7 +2142,7 @@ function findStaticPropertyType(node: TSTypeLiteral, key: string) { !m.computed && getId(m.key) === key && m.typeAnnotation, - ) + ) as TSPropertySignature | undefined return prop && prop.typeAnnotation!.typeAnnotation } @@ -2051,7 +2161,7 @@ function resolveReturnType( } if (!resolved) return if (resolved.type === 'TSFunctionType') { - return resolved.typeAnnotation?.typeAnnotation + return resolved.returnType?.typeAnnotation } if (resolved.type === 'TSDeclareFunction') { return resolved.returnType diff --git a/packages/compiler-sfc/src/script/utils.ts b/packages/compiler-sfc/src/script/utils.ts index 1b7da0e3497..5a3a78af1fe 100644 --- a/packages/compiler-sfc/src/script/utils.ts +++ b/packages/compiler-sfc/src/script/utils.ts @@ -1,12 +1,13 @@ import type { CallExpression, - Expression, Identifier, ImportDefaultSpecifier, ImportNamespaceSpecifier, ImportSpecifier, Node, StringLiteral, + TSEntityName, + TSQualifiedName, } from '@babel/types' import path from 'path' @@ -69,14 +70,16 @@ export function getImportedName( return 'default' } -export function getId(node: Identifier | StringLiteral): string -export function getId(node: Expression): string | null -export function getId(node: Expression) { +export function getId(node: Identifier | StringLiteral | TSEntityName): string +export function getId(node: Node): string | null +export function getId(node: Node) { return node.type === 'Identifier' ? node.name : node.type === 'StringLiteral' ? node.value - : null + : node.type === 'TSQualifiedName' + ? getId(node.left as TSQualifiedName) + : null } const identity = (str: string) => str diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 960433e438c..c3bf9cc663d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,11 +7,11 @@ settings: catalogs: default: '@babel/parser': - specifier: ^7.28.4 - version: 7.28.4 + specifier: ^8.0.0-beta.2 + version: 8.0.0-beta.2 '@babel/types': - specifier: ^7.28.4 - version: 7.28.4 + specifier: ^8.0.0-beta.2 + version: 8.0.0-beta.2 '@vitejs/plugin-vue': specifier: ^6.0.1 version: 6.0.1 @@ -34,10 +34,10 @@ importers: devDependencies: '@babel/parser': specifier: 'catalog:' - version: 7.28.4 + version: 8.0.0-beta.2 '@babel/types': specifier: 'catalog:' - version: 7.28.4 + version: 8.0.0-beta.2 '@rollup/plugin-alias': specifier: ^5.1.1 version: 5.1.1(rollup@4.52.2) @@ -248,7 +248,7 @@ importers: dependencies: '@babel/parser': specifier: 'catalog:' - version: 7.28.4 + version: 8.0.0-beta.2 '@vue/shared': specifier: workspace:* version: link:../shared @@ -264,7 +264,7 @@ importers: devDependencies: '@babel/types': specifier: 'catalog:' - version: 7.28.4 + version: 8.0.0-beta.2 packages/compiler-dom: dependencies: @@ -279,7 +279,7 @@ importers: dependencies: '@babel/parser': specifier: 'catalog:' - version: 7.28.4 + version: 8.0.0-beta.2 '@vue/compiler-core': specifier: workspace:* version: link:../compiler-core @@ -307,7 +307,7 @@ importers: devDependencies: '@babel/types': specifier: 'catalog:' - version: 7.28.4 + version: 8.0.0-beta.2 '@vue/consolidate': specifier: ^1.0.0 version: 1.0.0 @@ -427,7 +427,7 @@ importers: dependencies: '@babel/parser': specifier: 'catalog:' - version: 7.28.4 + version: 8.0.0-beta.2 estree-walker: specifier: 'catalog:' version: 2.0.2 @@ -461,19 +461,36 @@ packages: resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} engines: {node: '>=6.9.0'} + '@babel/helper-string-parser@8.0.0-beta.2': + resolution: {integrity: sha512-AmrScvsE0jJzEGEmhM+KNg9IYZFmmvDmfN903qDnMR3fWKZ5UGLACAyb0dcaYFDatW/Ru21w8SzOZy8qP6Ix+A==} + engines: {node: ^20.19.0 || >=22.12.0} + '@babel/helper-validator-identifier@7.27.1': resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} engines: {node: '>=6.9.0'} + '@babel/helper-validator-identifier@8.0.0-beta.2': + resolution: {integrity: sha512-n5STLJIc4loOeI2G+mMZwYIiztQWZdy+3du0cspVWoUjZ4AgkCIld4XcY0jJPgLImStacvJKCO6qCf0UBMpETw==} + engines: {node: ^20.19.0 || >=22.12.0} + '@babel/parser@7.28.4': resolution: {integrity: sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==} engines: {node: '>=6.0.0'} hasBin: true + '@babel/parser@8.0.0-beta.2': + resolution: {integrity: sha512-91A5GVa6ROgyF1uzDvGJlscf9tktIrXS4ohp8cnW22gwX1ERMw9m9KzdtoFgfdzt9rmSXKYtjwHhh5samc4Pdg==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + '@babel/types@7.28.4': resolution: {integrity: sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==} engines: {node: '>=6.9.0'} + '@babel/types@8.0.0-beta.2': + resolution: {integrity: sha512-dnlxcfISuGiHBhyq+Jmbp14lis59INgqHX/i95bfZLqIvBztd5F1jMZ0ozq36z3eWs3hXUG3AgS867wkaeRKfA==} + engines: {node: ^20.19.0 || >=22.12.0} + '@bcoe/v8-coverage@1.0.2': resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} engines: {node: '>=18'} @@ -3692,17 +3709,30 @@ snapshots: '@babel/helper-string-parser@7.27.1': {} + '@babel/helper-string-parser@8.0.0-beta.2': {} + '@babel/helper-validator-identifier@7.27.1': {} + '@babel/helper-validator-identifier@8.0.0-beta.2': {} + '@babel/parser@7.28.4': dependencies: '@babel/types': 7.28.4 + '@babel/parser@8.0.0-beta.2': + dependencies: + '@babel/types': 8.0.0-beta.2 + '@babel/types@7.28.4': dependencies: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.27.1 + '@babel/types@8.0.0-beta.2': + dependencies: + '@babel/helper-string-parser': 8.0.0-beta.2 + '@babel/helper-validator-identifier': 8.0.0-beta.2 + '@bcoe/v8-coverage@1.0.2': {} '@conventional-changelog/git-client@1.0.1(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.0.0)': diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index bd17cfdd721..bab103a7b6d 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -3,8 +3,8 @@ packages: - 'packages-private/*' catalog: - '@babel/parser': ^7.28.4 - '@babel/types': ^7.28.4 + '@babel/parser': ^8.0.0-beta.2 + '@babel/types': ^8.0.0-beta.2 'estree-walker': ^2.0.2 'magic-string': ^0.30.19 'source-map-js': ^1.2.1 diff --git a/scripts/inline-enums.js b/scripts/inline-enums.js index b1baaa6c5c3..93ab388be2d 100644 --- a/scripts/inline-enums.js +++ b/scripts/inline-enums.js @@ -90,8 +90,8 @@ export function scanEnums() { /** @type {Array} */ const members = [] - for (let i = 0; i < decl.members.length; i++) { - const e = decl.members[i] + for (let i = 0; i < decl.body.members.length; i++) { + const e = decl.body.members[i] const key = e.id.type === 'Identifier' ? e.id.name : e.id.value const fullKey = /** @type {const} */ (`${id}.${key}`) const saveValue = (/** @type {string | number} */ value) => {