Skip to content

Commit 271df09

Browse files
committed
fix(compiler-sfc): normalize windows paths when resolving types
1 parent 33adc2a commit 271df09

File tree

2 files changed

+20
-9
lines changed

2 files changed

+20
-9
lines changed

packages/compiler-sfc/src/script/resolveType.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ import {
2525
UNKNOWN_TYPE,
2626
createGetCanonicalFileName,
2727
getId,
28-
getImportedName
28+
getImportedName,
29+
normalizePath
2930
} from './utils'
3031
import { ScriptCompileContext, resolveParserPlugins } from './context'
3132
import { ImportBinding, SFCScriptCompileOptions } from '../compileScript'
@@ -34,7 +35,7 @@ import { parse as babelParse } from '@babel/parser'
3435
import { parse } from '../parse'
3536
import { createCache } from '../cache'
3637
import type TS from 'typescript'
37-
import { join, extname, dirname } from 'path'
38+
import path from 'path'
3839

3940
/**
4041
* TypeResolveContext is compatible with ScriptCompileContext
@@ -577,8 +578,7 @@ function resolveGlobalScope(ctx: TypeResolveContext): TypeScope[] | undefined {
577578
throw new Error('[vue/compiler-sfc] globalTypeFiles requires fs access.')
578579
}
579580
return ctx.options.globalTypeFiles.map(file =>
580-
// TODO: differentiate ambient vs non-ambient module
581-
fileToScope(file, fs, ctx.options.babelParserPlugins, true)
581+
fileToScope(normalizePath(file), fs, ctx.options.babelParserPlugins, true)
582582
)
583583
}
584584
}
@@ -616,7 +616,7 @@ function resolveTypeFromImport(
616616

617617
if (source.startsWith('.')) {
618618
// relative import - fast path
619-
const filename = join(containingFile, '..', source)
619+
const filename = path.join(containingFile, '..', source)
620620
resolved = resolveExt(filename, fs)
621621
} else {
622622
// module or aliased import - use full TS resolution, only supported in Node
@@ -642,6 +642,8 @@ function resolveTypeFromImport(
642642
}
643643

644644
if (resolved) {
645+
resolved = normalizePath(resolved)
646+
645647
// (hmr) register dependency file on ctx
646648
;(ctx.deps || (ctx.deps = new Set())).add(resolved)
647649

@@ -694,7 +696,8 @@ function resolveWithTS(
694696
let options: TS.CompilerOptions
695697
let cache: TS.ModuleResolutionCache | undefined
696698
if (configPath) {
697-
const cached = tsConfigCache.get(configPath)
699+
const normalizedConfigPath = normalizePath(configPath)
700+
const cached = tsConfigCache.get(normalizedConfigPath)
698701
if (!cached) {
699702
// The only case where `fs` is NOT `ts.sys` is during tests.
700703
// parse config host requires an extra `readDirectory` method
@@ -709,7 +712,7 @@ function resolveWithTS(
709712
const parsed = ts.parseJsonConfigFileContent(
710713
ts.readConfigFile(configPath, fs.readFile).config,
711714
parseConfigHost,
712-
dirname(configPath),
715+
path.dirname(configPath),
713716
undefined,
714717
configPath
715718
)
@@ -719,7 +722,7 @@ function resolveWithTS(
719722
createGetCanonicalFileName(ts.sys.useCaseSensitiveFileNames),
720723
options
721724
)
722-
tsConfigCache.set(configPath, { options, cache })
725+
tsConfigCache.set(normalizedConfigPath, { options, cache })
723726
} else {
724727
;({ options, cache } = cached)
725728
}
@@ -777,7 +780,7 @@ function parseFile(
777780
content: string,
778781
parserPlugins?: SFCScriptCompileOptions['babelParserPlugins']
779782
): Statement[] {
780-
const ext = extname(filename)
783+
const ext = path.extname(filename)
781784
if (ext === '.ts' || ext === '.tsx') {
782785
return babelParse(content, {
783786
plugins: resolveParserPlugins(ext.slice(1), parserPlugins),

packages/compiler-sfc/src/script/utils.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
Node,
99
StringLiteral
1010
} from '@babel/types'
11+
import path from 'path'
1112
import { TS_NODE_TYPES } from '@vue/compiler-dom'
1213

1314
export const UNKNOWN_TYPE = 'Unknown'
@@ -97,3 +98,10 @@ function toFileNameLowerCase(x: string) {
9798
export function createGetCanonicalFileName(useCaseSensitiveFileNames: boolean) {
9899
return useCaseSensitiveFileNames ? identity : toFileNameLowerCase
99100
}
101+
102+
const windowsSlashRE = /\\/g
103+
export function normalizePath(p: string) {
104+
// in the browser build, the polyfill doesn't expose posix, but defualts to
105+
// posix behavior.
106+
return (path.posix || path).normalize(p.replace(windowsSlashRE, '/'))
107+
}

0 commit comments

Comments
 (0)