From 5a349e270eec5c3da17209c18ae7c3416ac4422c Mon Sep 17 00:00:00 2001 From: Ahn Date: Wed, 29 Apr 2020 11:14:21 +0200 Subject: [PATCH] chore: use Map for compiler memory cache (#1575) --- src/compiler/compiler-utils.ts | 4 ++-- src/compiler/instance.ts | 16 +++++++-------- src/compiler/language-service.ts | 34 +++++++++++++++++--------------- src/compiler/transpiler.ts | 2 +- src/types.ts | 4 +--- 5 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/compiler/compiler-utils.ts b/src/compiler/compiler-utils.ts index dfc4ee81a0..3666a714b2 100644 --- a/src/compiler/compiler-utils.ts +++ b/src/compiler/compiler-utils.ts @@ -117,7 +117,7 @@ export function getAndCacheProjectReference( files: TSFiles, projectReferences: ReadonlyArray<_ts.ProjectReference> | undefined, ) { - const file = files[filePath] + const file = files.get(filePath) if (file?.projectReference) { return file.projectReference.project } @@ -156,7 +156,7 @@ function getAndCacheOutputJSFileName( projectReference: _ts.ResolvedProjectReference, files: TSFiles, ) { - const file = files[inputFileName] + const file = files.get(inputFileName) if (file?.projectReference?.outputFileName) { return file.projectReference.outputFileName } diff --git a/src/compiler/instance.ts b/src/compiler/instance.ts index 19fdfc01a2..901f05bdca 100644 --- a/src/compiler/instance.ts +++ b/src/compiler/instance.ts @@ -4,7 +4,7 @@ import mkdirp = require('mkdirp') import { basename, extname } from 'path' import { ConfigSet } from '../config/config-set' -import { CompileFn, CompilerInstance, MemoryCache, TsCompiler } from '../types' +import { CompileFn, CompilerInstance, MemoryCache, TSFile, TsCompiler } from '../types' import { getResolvedModulesCache } from './compiler-utils' import { initializeLanguageServiceInstance } from './language-service' @@ -55,10 +55,10 @@ const compileAndCacheResult = ( const [value, sourceMap] = compileFn(code, fileName, lineOffset) const output = updateOutput(value, fileName, sourceMap, getExtension) - memoryCache.files[fileName] = { - ...memoryCache.files[fileName], + memoryCache.files.set(fileName, { + ...memoryCache.files.get(fileName)!, output, - } + }) return output } @@ -78,7 +78,7 @@ export const createCompilerInstance = (configs: ConfigSet): TsCompiler => { const ts = configs.compilerModule // Require the TypeScript compiler and configuration. const extensions = ['.ts', '.tsx'] const memoryCache: MemoryCache = { - files: Object.create(null), + files: new Map(), resolvedModules: Object.create(null), } // Enable `allowJs` when flag is set. @@ -95,11 +95,11 @@ export const createCompilerInstance = (configs: ConfigSet): TsCompiler => { memoryCache.resolvedModules = JSON.parse(fsMemoryCache) } catch (e) {} } - /* istanbul ignore next (we leave this for e2e) */ + // Initialize memory cache for typescript compiler configs.typescript.fileNames.forEach(fileName => { - memoryCache.files[fileName] = { + memoryCache.files.set(fileName, { version: 0, - } + }) }) /** * Get the extension for a transpiled file. diff --git a/src/compiler/language-service.ts b/src/compiler/language-service.ts index 5fa511e6f2..9465d43447 100644 --- a/src/compiler/language-service.ts +++ b/src/compiler/language-service.ts @@ -44,6 +44,9 @@ export const initializeLanguageServiceInstance = ( call: null, [LogContexts.logLevel]: LogLevels.trace, } + function isFileInCache(fileName: string) { + return memoryCache.files.has(fileName) && memoryCache.files.get(fileName)!.version !== 0 + } let projectVersion = 1 // Set the file contents into cache. /* istanbul ignore next (cover by e2e) */ @@ -51,23 +54,23 @@ export const initializeLanguageServiceInstance = ( logger.debug({ fileName }, `updateMemoryCache(): update memory cache for language service`) let shouldIncrementProjectVersion = false - const isFileInCache = hasOwn.call(memoryCache.files, fileName) && memoryCache.files[fileName].version !== 0 - if (!isFileInCache) { - memoryCache.files[fileName] = { + const hit = isFileInCache(fileName) + if (!hit) { + memoryCache.files.set(fileName, { text: contents, version: 1, - } + }) shouldIncrementProjectVersion = true } else { - const previousContents = memoryCache.files[fileName].text + const previousContents = memoryCache.files.get(fileName)!.text // Avoid incrementing cache when nothing has changed. if (previousContents !== contents) { - memoryCache.files[fileName] = { + memoryCache.files.set(fileName, { text: contents, - version: memoryCache.files[fileName].version + 1, - } + version: memoryCache.files.get(fileName)!.version + 1, + }) // Only bump project version when file is modified in cache, not when discovered for the first time - if (isFileInCache) shouldIncrementProjectVersion = true + if (hit) shouldIncrementProjectVersion = true } /** * When a file is from node_modules or referenced to a referenced project and jest wants to transform it, we need @@ -83,10 +86,10 @@ export const initializeLanguageServiceInstance = ( const serviceHost: _ts.LanguageServiceHost = { getProjectVersion: () => String(projectVersion), getProjectReferences: () => projectReferences, - getScriptFileNames: () => Object.keys(memoryCache.files), + getScriptFileNames: () => [...memoryCache.files.keys()], getScriptVersion: (fileName: string) => { const normalizedFileName = normalize(fileName) - const version = memoryCache.files[normalizedFileName].version + const version = memoryCache.files.get(normalizedFileName)!.version // We need to return `undefined` and not a string here because TypeScript will use // `getScriptVersion` and compare against their own version - which can be `undefined`. @@ -97,19 +100,18 @@ export const initializeLanguageServiceInstance = ( }, getScriptSnapshot(fileName: string) { const normalizedFileName = normalize(fileName) - const hit = - hasOwn.call(memoryCache.files, normalizedFileName) && memoryCache.files[normalizedFileName].version !== 0 + const hit = memoryCache.files.has(normalizedFileName) && memoryCache.files.get(normalizedFileName)!.version !== 0 logger.trace({ normalizedFileName, cacheHit: hit }, `getScriptSnapshot():`, 'cache', hit ? 'hit' : 'miss') // Read contents from TypeScript memory cache. if (!hit) { - memoryCache.files[normalizedFileName] = { + memoryCache.files.set(normalizedFileName, { text: ts.sys.readFile(normalizedFileName), version: 1, - } + }) } - const contents = memoryCache.files[normalizedFileName]?.text + const contents = memoryCache.files.get(normalizedFileName)?.text if (contents === undefined) return diff --git a/src/compiler/transpiler.ts b/src/compiler/transpiler.ts index fce084ac87..c25b844234 100644 --- a/src/compiler/transpiler.ts +++ b/src/compiler/transpiler.ts @@ -27,7 +27,7 @@ export const initializeTranspilerInstance = ( : ts.createProgram([], options) /* istanbul ignore next (we leave this for e2e) */ const updateFileInCache = (contents: string, filePath: string) => { - const file = memoryCache.files[filePath] + const file = memoryCache.files.get(filePath) if (file && file.text !== contents) { file.version++ file.text = contents diff --git a/src/types.ts b/src/types.ts index e22c61c0a0..8118577fdc 100644 --- a/src/types.ts +++ b/src/types.ts @@ -239,9 +239,7 @@ export interface AstTransformerDesc { factory(cs: ConfigSet): _ts.TransformerFactory<_ts.SourceFile> } /** where key is filepath */ -export interface TSFiles { - [filePath: string]: TSFile -} +export type TSFiles = Map export interface TSFile { text?: string output?: string