chrome: cache tsconfig for folder (#32477)

Fixes https://github.com/microsoft/playwright/issues/32459
This commit is contained in:
Pavel Feldman 2024-09-05 21:36:13 -07:00 committed by GitHub
parent f0e13164d7
commit 16cef9901d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 51 additions and 51 deletions

View File

@ -52,49 +52,12 @@ export interface LoadedTsConfig {
allowJs?: boolean;
}
export function tsConfigLoader(tsconfigPathOrDirecotry: string): LoadedTsConfig[] {
const configPath = resolveConfigPath(tsconfigPathOrDirecotry);
if (!configPath)
return [];
export function loadTsConfig(configPath: string): LoadedTsConfig[] {
const references: LoadedTsConfig[] = [];
const config = loadTsConfig(configPath, references);
const config = innerLoadTsConfig(configPath, references);
return [config, ...references];
}
function resolveConfigPath(tsconfigPathOrDirecotry: string): string | undefined {
if (fs.statSync(tsconfigPathOrDirecotry).isFile()) {
return path.resolve(tsconfigPathOrDirecotry);
}
const configAbsolutePath = walkForTsConfig(tsconfigPathOrDirecotry);
return configAbsolutePath ? path.resolve(configAbsolutePath) : undefined;
}
export function walkForTsConfig(
directory: string,
existsSync: (path: string) => boolean = fs.existsSync
): string | undefined {
const tsconfigPath = path.join(directory, "./tsconfig.json");
if (existsSync(tsconfigPath)) {
return tsconfigPath;
}
const jsconfigPath = path.join(directory, "./jsconfig.json");
if (existsSync(jsconfigPath)) {
return jsconfigPath;
}
const parentDirectory = path.join(directory, "../");
// If we reached the top
if (directory === parentDirectory) {
return undefined;
}
return walkForTsConfig(parentDirectory, existsSync);
}
function resolveConfigFile(baseConfigFile: string, referencedConfigFile: string) {
if (!referencedConfigFile.endsWith('.json'))
referencedConfigFile += '.json';
@ -106,7 +69,7 @@ function resolveConfigFile(baseConfigFile: string, referencedConfigFile: string)
return resolvedConfigFile;
}
function loadTsConfig(
function innerLoadTsConfig(
configFilePath: string,
references: LoadedTsConfig[],
visited = new Map<string, LoadedTsConfig>(),
@ -130,7 +93,7 @@ function loadTsConfig(
const extendsArray = Array.isArray(parsedConfig.extends) ? parsedConfig.extends : (parsedConfig.extends ? [parsedConfig.extends] : []);
for (const extendedConfig of extendsArray) {
const extendedConfigPath = resolveConfigFile(configFilePath, extendedConfig);
const base = loadTsConfig(extendedConfigPath, references, visited);
const base = innerLoadTsConfig(extendedConfigPath, references, visited);
// Retain result instance, so that caching works.
Object.assign(result, base, { tsConfigPath: configFilePath });
}
@ -154,7 +117,7 @@ function loadTsConfig(
}
for (const ref of parsedConfig.references || [])
references.push(loadTsConfig(resolveConfigFile(configFilePath, ref.path), references, visited));
references.push(innerLoadTsConfig(resolveConfigFile(configFilePath, ref.path), references, visited));
if (path.basename(configFilePath) === 'jsconfig.json' && result.allowJs === undefined)
result.allowJs = true;

View File

@ -15,12 +15,13 @@
*/
import crypto from 'crypto';
import fs from 'fs';
import path from 'path';
import url from 'url';
import { sourceMapSupport, pirates } from '../utilsBundle';
import type { Location } from '../../types/testReporter';
import type { LoadedTsConfig } from '../third_party/tsconfig-loader';
import { tsConfigLoader } from '../third_party/tsconfig-loader';
import { loadTsConfig } from '../third_party/tsconfig-loader';
import Module from 'module';
import type { BabelPlugin, BabelTransformFunction } from './babelBundle';
import { createFileMatcher, fileIsModule, resolveImportSpecifierExtension } from '../util';
@ -57,14 +58,15 @@ export function transformConfig(): TransformConfig {
return _transformConfig;
}
let _singleTSConfig: string | undefined;
let _singleTSConfigPath: string | undefined;
let _singleTSConfig: ParsedTsConfigData[] | undefined;
export function setSingleTSConfig(value: string | undefined) {
_singleTSConfig = value;
_singleTSConfigPath = value;
}
export function singleTSConfig(): string | undefined {
return _singleTSConfig;
return _singleTSConfigPath;
}
function validateTsConfig(tsconfig: LoadedTsConfig): ParsedTsConfigData {
@ -81,12 +83,47 @@ function validateTsConfig(tsconfig: LoadedTsConfig): ParsedTsConfigData {
}
function loadAndValidateTsconfigsForFile(file: string): ParsedTsConfigData[] {
const tsconfigPathOrDirecotry = _singleTSConfig || path.dirname(file);
if (!cachedTSConfigs.has(tsconfigPathOrDirecotry)) {
const loaded = tsConfigLoader(tsconfigPathOrDirecotry);
cachedTSConfigs.set(tsconfigPathOrDirecotry, loaded.map(validateTsConfig));
if (_singleTSConfigPath && !_singleTSConfig)
_singleTSConfig = loadTsConfig(_singleTSConfigPath).map(validateTsConfig);
if (_singleTSConfig)
return _singleTSConfig;
return loadAndValidateTsconfigsForFolder(path.dirname(file));
}
function loadAndValidateTsconfigsForFolder(folder: string): ParsedTsConfigData[] {
const foldersWithConfig: string[] = [];
let currentFolder = path.resolve(folder);
let result: ParsedTsConfigData[] | undefined;
while (true) {
const cached = cachedTSConfigs.get(currentFolder);
if (cached) {
result = cached;
break;
}
foldersWithConfig.push(currentFolder);
for (const name of ['tsconfig.json', 'jsconfig.json']) {
const configPath = path.join(currentFolder, name);
if (fs.existsSync(configPath)) {
const loaded = loadTsConfig(configPath);
result = loaded.map(validateTsConfig);
break;
}
}
if (result)
break;
const parentFolder = path.resolve(currentFolder, '../');
if (currentFolder === parentFolder)
break;
currentFolder = parentFolder;
}
return cachedTSConfigs.get(tsconfigPathOrDirecotry)!;
result = result || [];
for (const folder of foldersWithConfig)
cachedTSConfigs.set(folder, result);
return result;
}
const pathSeparator = process.platform === 'win32' ? ';' : ':';