fix(compiler-sfc): simulate `allowArbitraryExtensions` on resolving type (#13301)
close #13295
This commit is contained in:
parent
772b0087cb
commit
f7ce5ae666
|
@ -1434,6 +1434,29 @@ describe('resolveType', () => {
|
||||||
colsLg: ['Number'],
|
colsLg: ['Number'],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('allowArbitraryExtensions', () => {
|
||||||
|
const files = {
|
||||||
|
'/foo.d.vue.ts': 'export type Foo = number;',
|
||||||
|
'/foo.vue': '<template><div /></template>',
|
||||||
|
'/bar.d.css.ts': 'export type Bar = string;',
|
||||||
|
'/bar.css': ':root { --color: red; }',
|
||||||
|
}
|
||||||
|
|
||||||
|
const { props } = resolve(
|
||||||
|
`
|
||||||
|
import { Foo } from './foo.vue'
|
||||||
|
import { Bar } from './bar.css'
|
||||||
|
defineProps<{ foo: Foo; bar: Bar }>()
|
||||||
|
`,
|
||||||
|
files,
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(props).toStrictEqual({
|
||||||
|
foo: ['Number'],
|
||||||
|
bar: ['String'],
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -860,13 +860,13 @@ function resolveFS(ctx: TypeResolveContext): FS | undefined {
|
||||||
}
|
}
|
||||||
return (ctx.fs = {
|
return (ctx.fs = {
|
||||||
fileExists(file) {
|
fileExists(file) {
|
||||||
if (file.endsWith('.vue.ts')) {
|
if (file.endsWith('.vue.ts') && !file.endsWith('.d.vue.ts')) {
|
||||||
file = file.replace(/\.ts$/, '')
|
file = file.replace(/\.ts$/, '')
|
||||||
}
|
}
|
||||||
return fs.fileExists(file)
|
return fs.fileExists(file)
|
||||||
},
|
},
|
||||||
readFile(file) {
|
readFile(file) {
|
||||||
if (file.endsWith('.vue.ts')) {
|
if (file.endsWith('.vue.ts') && !file.endsWith('.d.vue.ts')) {
|
||||||
file = file.replace(/\.ts$/, '')
|
file = file.replace(/\.ts$/, '')
|
||||||
}
|
}
|
||||||
return fs.readFile(file)
|
return fs.readFile(file)
|
||||||
|
@ -1059,7 +1059,7 @@ function resolveWithTS(
|
||||||
|
|
||||||
if (res.resolvedModule) {
|
if (res.resolvedModule) {
|
||||||
let filename = res.resolvedModule.resolvedFileName
|
let filename = res.resolvedModule.resolvedFileName
|
||||||
if (filename.endsWith('.vue.ts')) {
|
if (filename.endsWith('.vue.ts') && !filename.endsWith('.d.vue.ts')) {
|
||||||
filename = filename.replace(/\.ts$/, '')
|
filename = filename.replace(/\.ts$/, '')
|
||||||
}
|
}
|
||||||
return fs.realpath ? fs.realpath(filename) : filename
|
return fs.realpath ? fs.realpath(filename) : filename
|
||||||
|
@ -1129,7 +1129,7 @@ export function fileToScope(
|
||||||
// fs should be guaranteed to exist here
|
// fs should be guaranteed to exist here
|
||||||
const fs = resolveFS(ctx)!
|
const fs = resolveFS(ctx)!
|
||||||
const source = fs.readFile(filename) || ''
|
const source = fs.readFile(filename) || ''
|
||||||
const body = parseFile(filename, source, ctx.options.babelParserPlugins)
|
const body = parseFile(filename, source, fs, ctx.options.babelParserPlugins)
|
||||||
const scope = new TypeScope(filename, source, 0, recordImports(body))
|
const scope = new TypeScope(filename, source, 0, recordImports(body))
|
||||||
recordTypes(ctx, body, scope, asGlobal)
|
recordTypes(ctx, body, scope, asGlobal)
|
||||||
fileToScopeCache.set(filename, scope)
|
fileToScopeCache.set(filename, scope)
|
||||||
|
@ -1139,6 +1139,7 @@ export function fileToScope(
|
||||||
function parseFile(
|
function parseFile(
|
||||||
filename: string,
|
filename: string,
|
||||||
content: string,
|
content: string,
|
||||||
|
fs: FS,
|
||||||
parserPlugins?: SFCScriptCompileOptions['babelParserPlugins'],
|
parserPlugins?: SFCScriptCompileOptions['babelParserPlugins'],
|
||||||
): Statement[] {
|
): Statement[] {
|
||||||
const ext = extname(filename)
|
const ext = extname(filename)
|
||||||
|
@ -1151,7 +1152,21 @@ function parseFile(
|
||||||
),
|
),
|
||||||
sourceType: 'module',
|
sourceType: 'module',
|
||||||
}).program.body
|
}).program.body
|
||||||
} else if (ext === '.vue') {
|
}
|
||||||
|
|
||||||
|
// simulate `allowArbitraryExtensions` on TypeScript >= 5.0
|
||||||
|
const isUnknownTypeSource = !/\.[cm]?[tj]sx?$/.test(filename)
|
||||||
|
const arbitraryTypeSource = `${filename.slice(0, -ext.length)}.d${ext}.ts`
|
||||||
|
const hasArbitraryTypeDeclaration =
|
||||||
|
isUnknownTypeSource && fs.fileExists(arbitraryTypeSource)
|
||||||
|
if (hasArbitraryTypeDeclaration) {
|
||||||
|
return babelParse(fs.readFile(arbitraryTypeSource)!, {
|
||||||
|
plugins: resolveParserPlugins('ts', parserPlugins, true),
|
||||||
|
sourceType: 'module',
|
||||||
|
}).program.body
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ext === '.vue') {
|
||||||
const {
|
const {
|
||||||
descriptor: { script, scriptSetup },
|
descriptor: { script, scriptSetup },
|
||||||
} = parse(content)
|
} = parse(content)
|
||||||
|
|
Loading…
Reference in New Issue