diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 514e4333af1e6..5bc854c5f9edc 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -1092,7 +1092,7 @@ namespace ts { declare const __filename: string; declare const __dirname: string; - export function getNodeMajorVersion(): number | undefined { + function getNodeVersion(): { major: number, minor: number } | undefined { if (typeof process === "undefined") { return undefined; } @@ -1104,7 +1104,17 @@ namespace ts { if (dot === -1) { return undefined; } - return parseInt(version.substring(1, dot)); + const major = parseInt(version.substring(1, dot)); + + const nextDot = version.indexOf(".", dot + 1); + const end = nextDot === -1 ? version.length : nextDot; + const minor = parseInt(version.substring(dot + 1, end)); + + return { major, minor }; + } + + export function getNodeMajorVersion(): number | undefined { + return getNodeVersion()?.major; } declare const ChakraHost: { @@ -1161,10 +1171,16 @@ namespace ts { from?(input: string, encoding?: string): any; } = require("buffer").Buffer; - const nodeVersion = getNodeMajorVersion(); - const isNode4OrLater = nodeVersion! >= 4; + const nodeVersion = getNodeVersion()!; + const isNode4OrLater = nodeVersion.major >= 4; const isLinuxOrMacOs = process.platform === "linux" || process.platform === "darwin"; + // Stat is no longer required as of Node 10.10 + // (https://github.com/nodejs/node/commit/ad97314418286b66a3c714b47559a7437b7cba85) + const getAccessibleFileSystemEntries = nodeVersion.major > 10 || (nodeVersion.major === 10 && nodeVersion.minor >= 10) + ? getAccessibleFileSystemEntriesWithoutStat + : getAccessibleFileSystemEntriesWithStat; + const platform: string = _os.platform(); const useCaseSensitiveFileNames = isFileSystemCaseSensitive(); const fsSupportsRecursiveFsWatch = isNode4OrLater && (process.platform === "win32" || process.platform === "darwin"); @@ -1614,7 +1630,7 @@ namespace ts { } } - function getAccessibleFileSystemEntries(path: string): FileSystemEntries { + function getAccessibleFileSystemEntriesWithStat(path: string): FileSystemEntries { perfLogger.logEvent("ReadDir: " + (path || ".")); try { const entries = _fs.readdirSync(path || ".").sort(); @@ -1650,6 +1666,34 @@ namespace ts { } } + // This version is faster, but isn't supported prior to 10.10. + function getAccessibleFileSystemEntriesWithoutStat(path: string): FileSystemEntries { + perfLogger.logEvent("ReadDir: " + (path || ".")); + try { + const entries = _fs.readdirSync(path || ".", { withFileTypes: true }); + const files: string[] = []; + const directories: string[] = []; + for (const entry of entries) { + const entryName = entry.name; + // This is necessary because on some file system node fails to exclude + // "." and "..". See https://github.com/nodejs/node/issues/4002 + if (entryName === "." || entryName === "..") { + continue; + } + if (entry.isFile()) { + files.push(entryName); + } + else if (entry.isDirectory()) { + directories.push(entryName); + } + } + return { files: files.sort(), directories: directories.sort() }; + } + catch (e) { + return emptyFileSystemEntries; + } + } + function readDirectory(path: string, extensions?: readonly string[], excludes?: readonly string[], includes?: readonly string[], depth?: number): string[] { return matchFiles(path, extensions, excludes, includes, useCaseSensitiveFileNames, process.cwd(), depth, getAccessibleFileSystemEntries, realpath); }