-
Notifications
You must be signed in to change notification settings - Fork 473
Expand file tree
/
Copy pathinstance.ts
More file actions
120 lines (109 loc) · 4.05 KB
/
instance.ts
File metadata and controls
120 lines (109 loc) · 4.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import { Logger } from 'bs-logger'
import { readFileSync } from 'fs'
import mkdirp = require('mkdirp')
import { basename, extname } from 'path'
import { ConfigSet } from '../config/config-set'
import { CompileFn, CompilerInstance, MemoryCache, TSFile, TsCompiler } from '../types'
import { getResolvedModulesCache } from './compiler-utils'
import { initializeLanguageServiceInstance } from './language-service'
import { initializeTranspilerInstance } from './transpiler'
/**
* Update the output remapping the source map.
*/
function updateOutput(
outputText: string,
normalizedFileName: string,
sourceMap: string,
getExtension: (fileName: string) => string,
) {
const base = basename(normalizedFileName)
const base64Map = Buffer.from(updateSourceMap(sourceMap, normalizedFileName), 'utf8').toString('base64')
const sourceMapContent = `data:application/json;charset=utf-8;base64,${base64Map}`
const sourceMapLength =
`${base}.map`.length + (getExtension(normalizedFileName).length - extname(normalizedFileName).length)
return outputText.slice(0, -sourceMapLength) + sourceMapContent
}
/**
* Update the source map contents for improved output.
*/
const updateSourceMap = (sourceMapText: string, normalizedFileName: string): string => {
const sourceMap = JSON.parse(sourceMapText)
sourceMap.file = normalizedFileName
sourceMap.sources = [normalizedFileName]
delete sourceMap.sourceRoot
return JSON.stringify(sourceMap)
}
/**
* Compile files which are provided by jest via transform config and cache the result in file system if users run with
* cache mode
*/
const compileAndCacheResult = (
memoryCache: MemoryCache,
compileFn: CompileFn,
getExtension: (fileName: string) => string,
logger: Logger,
) => (code: string, fileName: string, lineOffset?: number) => {
logger.debug({ fileName }, 'compileAndCacheResult(): get compile output')
const [value, sourceMap] = compileFn(code, fileName, lineOffset)
const output = updateOutput(value, fileName, sourceMap, getExtension)
memoryCache.files.set(fileName, {
...memoryCache.files.get(fileName)!, // eslint-disable-line @typescript-eslint/no-non-null-assertion
output,
})
return output
}
/**
* Register TypeScript compiler instance.
*
* @internal
*/
export const createCompilerInstance = (configs: ConfigSet): TsCompiler => {
const logger = configs.logger.child({ namespace: 'ts-compiler' })
const {
parsedTsConfig: { options: compilerOptions },
tsJest,
} = configs
const cacheDir = configs.tsCacheDir
const ts = configs.compilerModule // Require the TypeScript compiler and configuration.
const extensions = ['.ts', '.tsx']
const memoryCache: MemoryCache = {
files: new Map<string, TSFile>(),
resolvedModules: Object.create(null),
}
// Enable `allowJs` when flag is set.
if (compilerOptions.allowJs) {
extensions.push('.js')
extensions.push('.jsx')
}
if (cacheDir) {
// Make sure the cache directory exists before continuing.
mkdirp.sync(cacheDir)
try {
const fsMemoryCache = readFileSync(getResolvedModulesCache(cacheDir), 'utf-8')
/* istanbul ignore next (covered by e2e) */
memoryCache.resolvedModules = JSON.parse(fsMemoryCache)
} catch (e) {}
}
// Initialize memory cache for typescript compiler
configs.parsedTsConfig.fileNames.forEach((fileName) => {
memoryCache.files.set(fileName, {
version: 0,
})
})
/**
* Get the extension for a transpiled file.
*/
const getExtension =
compilerOptions.jsx === ts.JsxEmit.Preserve
? (path: string) => (/\.[tj]sx$/.test(path) ? '.jsx' : '.js')
: (_: string) => '.js'
let compilerInstance: CompilerInstance
if (!tsJest.isolatedModules) {
// Use language services by default
compilerInstance = initializeLanguageServiceInstance(configs, memoryCache, logger)
} else {
compilerInstance = initializeTranspilerInstance(configs, memoryCache, logger)
}
const compile = compileAndCacheResult(memoryCache, compilerInstance.compileFn, getExtension, logger)
return { cwd: configs.cwd, compile, program: compilerInstance.program }
}