@@ -45,6 +45,7 @@ namespace ts {
4545 [ "es2018.promise" , "lib.es2018.promise.d.ts" ] ,
4646 [ "es2018.regexp" , "lib.es2018.regexp.d.ts" ] ,
4747 [ "es2019.array" , "lib.es2019.array.d.ts" ] ,
48+ [ "es2019.object" , "lib.es2019.object.d.ts" ] ,
4849 [ "es2019.string" , "lib.es2019.string.d.ts" ] ,
4950 [ "es2019.symbol" , "lib.es2019.symbol.d.ts" ] ,
5051 [ "es2020.string" , "lib.es2020.string.d.ts" ] ,
@@ -218,6 +219,7 @@ namespace ts {
218219 } ) ,
219220 affectsSourceFile : true ,
220221 affectsModuleResolution : true ,
222+ affectsEmit : true ,
221223 paramType : Diagnostics . VERSION ,
222224 showInSimplifiedHelpView : true ,
223225 category : Diagnostics . Basic_Options ,
@@ -1345,7 +1347,12 @@ namespace ts {
13451347 /**
13461348 * Reads the config file, reports errors if any and exits if the config file cannot be found
13471349 */
1348- export function getParsedCommandLineOfConfigFile ( configFileName : string , optionsToExtend : CompilerOptions , host : ParseConfigFileHost ) : ParsedCommandLine | undefined {
1350+ export function getParsedCommandLineOfConfigFile (
1351+ configFileName : string ,
1352+ optionsToExtend : CompilerOptions ,
1353+ host : ParseConfigFileHost ,
1354+ extendedConfigCache ?: Map < ExtendedConfigCacheEntry >
1355+ ) : ParsedCommandLine | undefined {
13491356 let configFileText : string | undefined ;
13501357 try {
13511358 configFileText = host . readFile ( configFileName ) ;
@@ -1366,7 +1373,16 @@ namespace ts {
13661373 result . path = toPath ( configFileName , cwd , createGetCanonicalFileName ( host . useCaseSensitiveFileNames ) ) ;
13671374 result . resolvedPath = result . path ;
13681375 result . originalFileName = result . fileName ;
1369- return parseJsonSourceFileConfigFileContent ( result , host , getNormalizedAbsolutePath ( getDirectoryPath ( configFileName ) , cwd ) , optionsToExtend , getNormalizedAbsolutePath ( configFileName , cwd ) ) ;
1376+ return parseJsonSourceFileConfigFileContent (
1377+ result ,
1378+ host ,
1379+ getNormalizedAbsolutePath ( getDirectoryPath ( configFileName ) , cwd ) ,
1380+ optionsToExtend ,
1381+ getNormalizedAbsolutePath ( configFileName , cwd ) ,
1382+ /*resolutionStack*/ undefined ,
1383+ /*extraFileExtension*/ undefined ,
1384+ extendedConfigCache
1385+ ) ;
13701386 }
13711387
13721388 /**
@@ -1980,8 +1996,8 @@ namespace ts {
19801996 * @param basePath A root directory to resolve relative path entries in the config
19811997 * file to. e.g. outDir
19821998 */
1983- export function parseJsonSourceFileConfigFileContent ( sourceFile : TsConfigSourceFile , host : ParseConfigHost , basePath : string , existingOptions ?: CompilerOptions , configFileName ?: string , resolutionStack ?: Path [ ] , extraFileExtensions ?: ReadonlyArray < FileExtensionInfo > ) : ParsedCommandLine {
1984- return parseJsonConfigFileContentWorker ( /*json*/ undefined , sourceFile , host , basePath , existingOptions , configFileName , resolutionStack , extraFileExtensions ) ;
1999+ export function parseJsonSourceFileConfigFileContent ( sourceFile : TsConfigSourceFile , host : ParseConfigHost , basePath : string , existingOptions ?: CompilerOptions , configFileName ?: string , resolutionStack ?: Path [ ] , extraFileExtensions ?: ReadonlyArray < FileExtensionInfo > , /* @internal */ extendedConfigCache ?: Map < ExtendedConfigCacheEntry > ) : ParsedCommandLine {
2000+ return parseJsonConfigFileContentWorker ( /*json*/ undefined , sourceFile , host , basePath , existingOptions , configFileName , resolutionStack , extraFileExtensions , extendedConfigCache ) ;
19852001 }
19862002
19872003 /*@internal */
@@ -2020,11 +2036,12 @@ namespace ts {
20202036 configFileName ?: string ,
20212037 resolutionStack : Path [ ] = [ ] ,
20222038 extraFileExtensions : ReadonlyArray < FileExtensionInfo > = [ ] ,
2039+ extendedConfigCache ?: Map < ExtendedConfigCacheEntry >
20232040 ) : ParsedCommandLine {
20242041 Debug . assert ( ( json === undefined && sourceFile !== undefined ) || ( json !== undefined && sourceFile === undefined ) ) ;
20252042 const errors : Diagnostic [ ] = [ ] ;
20262043
2027- const parsedConfig = parseConfig ( json , sourceFile , host , basePath , configFileName , resolutionStack , errors ) ;
2044+ const parsedConfig = parseConfig ( json , sourceFile , host , basePath , configFileName , resolutionStack , errors , extendedConfigCache ) ;
20282045 const { raw } = parsedConfig ;
20292046 const options = extend ( existingOptions , parsedConfig . options || { } ) ;
20302047 options . configFilePath = configFileName && normalizeSlashes ( configFileName ) ;
@@ -2172,7 +2189,7 @@ namespace ts {
21722189 return existingErrors !== configParseDiagnostics . length ;
21732190 }
21742191
2175- interface ParsedTsconfig {
2192+ export interface ParsedTsconfig {
21762193 raw : any ;
21772194 options ?: CompilerOptions ;
21782195 typeAcquisition ?: TypeAcquisition ;
@@ -2191,13 +2208,14 @@ namespace ts {
21912208 * It does *not* resolve the included files.
21922209 */
21932210 function parseConfig (
2194- json : any ,
2195- sourceFile : TsConfigSourceFile | undefined ,
2196- host : ParseConfigHost ,
2197- basePath : string ,
2198- configFileName : string | undefined ,
2199- resolutionStack : string [ ] ,
2200- errors : Push < Diagnostic > ,
2211+ json : any ,
2212+ sourceFile : TsConfigSourceFile | undefined ,
2213+ host : ParseConfigHost ,
2214+ basePath : string ,
2215+ configFileName : string | undefined ,
2216+ resolutionStack : string [ ] ,
2217+ errors : Push < Diagnostic > ,
2218+ extendedConfigCache ?: Map < ExtendedConfigCacheEntry >
22012219 ) : ParsedTsconfig {
22022220 basePath = normalizeSlashes ( basePath ) ;
22032221 const resolvedPath = getNormalizedAbsolutePath ( configFileName || "" , basePath ) ;
@@ -2214,7 +2232,7 @@ namespace ts {
22142232 if ( ownConfig . extendedConfigPath ) {
22152233 // copy the resolution stack so it is never reused between branches in potential diamond-problem scenarios.
22162234 resolutionStack = resolutionStack . concat ( [ resolvedPath ] ) ;
2217- const extendedConfig = getExtendedConfig ( sourceFile , ownConfig . extendedConfigPath , host , basePath , resolutionStack , errors ) ;
2235+ const extendedConfig = getExtendedConfig ( sourceFile , ownConfig . extendedConfigPath , host , basePath , resolutionStack , errors , extendedConfigCache ) ;
22182236 if ( extendedConfig && isSuccessfulParsedTsconfig ( extendedConfig ) ) {
22192237 const baseRaw = extendedConfig . raw ;
22202238 const raw = ownConfig . raw ;
@@ -2358,47 +2376,65 @@ namespace ts {
23582376 return undefined ;
23592377 }
23602378
2379+ export interface ExtendedConfigCacheEntry {
2380+ extendedResult : TsConfigSourceFile ;
2381+ extendedConfig : ParsedTsconfig | undefined ;
2382+ }
2383+
23612384 function getExtendedConfig (
23622385 sourceFile : TsConfigSourceFile | undefined ,
23632386 extendedConfigPath : string ,
23642387 host : ParseConfigHost ,
23652388 basePath : string ,
23662389 resolutionStack : string [ ] ,
23672390 errors : Push < Diagnostic > ,
2391+ extendedConfigCache ?: Map < ExtendedConfigCacheEntry >
23682392 ) : ParsedTsconfig | undefined {
2369- const extendedResult = readJsonConfigFile ( extendedConfigPath , path => host . readFile ( path ) ) ;
2393+ const path = host . useCaseSensitiveFileNames ? extendedConfigPath : toLowerCase ( extendedConfigPath ) ;
2394+ let value : ExtendedConfigCacheEntry | undefined ;
2395+ let extendedResult : TsConfigSourceFile ;
2396+ let extendedConfig : ParsedTsconfig | undefined ;
2397+ if ( extendedConfigCache && ( value = extendedConfigCache . get ( path ) ) ) {
2398+ ( { extendedResult, extendedConfig } = value ) ;
2399+ }
2400+ else {
2401+ extendedResult = readJsonConfigFile ( extendedConfigPath , path => host . readFile ( path ) ) ;
2402+ if ( ! extendedResult . parseDiagnostics . length ) {
2403+ const extendedDirname = getDirectoryPath ( extendedConfigPath ) ;
2404+ extendedConfig = parseConfig ( /*json*/ undefined , extendedResult , host , extendedDirname ,
2405+ getBaseFileName ( extendedConfigPath ) , resolutionStack , errors , extendedConfigCache ) ;
2406+
2407+ if ( isSuccessfulParsedTsconfig ( extendedConfig ) ) {
2408+ // Update the paths to reflect base path
2409+ const relativeDifference = convertToRelativePath ( extendedDirname , basePath , identity ) ;
2410+ const updatePath = ( path : string ) => isRootedDiskPath ( path ) ? path : combinePaths ( relativeDifference , path ) ;
2411+ const mapPropertiesInRawIfNotUndefined = ( propertyName : string ) => {
2412+ if ( raw [ propertyName ] ) {
2413+ raw [ propertyName ] = map ( raw [ propertyName ] , updatePath ) ;
2414+ }
2415+ } ;
2416+
2417+ const { raw } = extendedConfig ;
2418+ mapPropertiesInRawIfNotUndefined ( "include" ) ;
2419+ mapPropertiesInRawIfNotUndefined ( "exclude" ) ;
2420+ mapPropertiesInRawIfNotUndefined ( "files" ) ;
2421+ }
2422+ }
2423+ if ( extendedConfigCache ) {
2424+ extendedConfigCache . set ( path , { extendedResult, extendedConfig } ) ;
2425+ }
2426+ }
23702427 if ( sourceFile ) {
23712428 sourceFile . extendedSourceFiles = [ extendedResult . fileName ] ;
2429+ if ( extendedResult . extendedSourceFiles ) {
2430+ sourceFile . extendedSourceFiles . push ( ...extendedResult . extendedSourceFiles ) ;
2431+ }
23722432 }
23732433 if ( extendedResult . parseDiagnostics . length ) {
23742434 errors . push ( ...extendedResult . parseDiagnostics ) ;
23752435 return undefined ;
23762436 }
2377-
2378- const extendedDirname = getDirectoryPath ( extendedConfigPath ) ;
2379- const extendedConfig = parseConfig ( /*json*/ undefined , extendedResult , host , extendedDirname ,
2380- getBaseFileName ( extendedConfigPath ) , resolutionStack , errors ) ;
2381- if ( sourceFile && extendedResult . extendedSourceFiles ) {
2382- sourceFile . extendedSourceFiles ! . push ( ...extendedResult . extendedSourceFiles ) ;
2383- }
2384-
2385- if ( isSuccessfulParsedTsconfig ( extendedConfig ) ) {
2386- // Update the paths to reflect base path
2387- const relativeDifference = convertToRelativePath ( extendedDirname , basePath , identity ) ;
2388- const updatePath = ( path : string ) => isRootedDiskPath ( path ) ? path : combinePaths ( relativeDifference , path ) ;
2389- const mapPropertiesInRawIfNotUndefined = ( propertyName : string ) => {
2390- if ( raw [ propertyName ] ) {
2391- raw [ propertyName ] = map ( raw [ propertyName ] , updatePath ) ;
2392- }
2393- } ;
2394-
2395- const { raw } = extendedConfig ;
2396- mapPropertiesInRawIfNotUndefined ( "include" ) ;
2397- mapPropertiesInRawIfNotUndefined ( "exclude" ) ;
2398- mapPropertiesInRawIfNotUndefined ( "files" ) ;
2399- }
2400-
2401- return extendedConfig ;
2437+ return extendedConfig ! ;
24022438 }
24032439
24042440 function convertCompileOnSaveOptionFromJson ( jsonOption : any , basePath : string , errors : Push < Diagnostic > ) : boolean {
0 commit comments