1- import createCacheKey from '@jest/create-cache-key-function'
21import type { CacheKeyOptions , TransformedSource , Transformer , TransformOptions } from '@jest/transform'
32import type { Config } from '@jest/types'
43import type { Logger } from 'bs-logger'
@@ -9,6 +8,7 @@ import { stringify } from './utils/json'
98import { JsonableValue } from './utils/jsonable-value'
109import { rootLogger } from './utils/logger'
1110import { Errors , interpolate } from './utils/messages'
11+ import { sha1 } from './utils/sha1'
1212
1313interface CachedConfigSet {
1414 configSet : ConfigSet
@@ -25,14 +25,65 @@ export class TsJestTransformer implements Transformer {
2525 private static readonly _cachedConfigSets : CachedConfigSet [ ] = [ ]
2626 protected readonly logger : Logger
2727 protected _transformCfgStr ! : string
28- protected _configSet ! : ConfigSet
2928
3029 constructor ( ) {
3130 this . logger = rootLogger . child ( { namespace : 'ts-jest-transformer' } )
3231
3332 this . logger . debug ( 'created new transformer' )
3433 }
3534
35+ /**
36+ * @public
37+ */
38+ configsFor ( jestConfig : Config . ProjectConfig ) : ConfigSet {
39+ const ccs : CachedConfigSet | undefined = TsJestTransformer . _cachedConfigSets . find (
40+ ( cs ) => cs . jestConfig . value === jestConfig ,
41+ )
42+ let configSet : ConfigSet
43+ if ( ccs ) {
44+ this . _transformCfgStr = ccs . transformerCfgStr
45+ configSet = ccs . configSet
46+ } else {
47+ // try to look-it up by stringified version
48+ const serializedJestCfg = stringify ( jestConfig )
49+ const serializedCcs = TsJestTransformer . _cachedConfigSets . find (
50+ ( cs ) => cs . jestConfig . serialized === serializedJestCfg ,
51+ )
52+ if ( serializedCcs ) {
53+ // update the object so that we can find it later
54+ // this happens because jest first calls getCacheKey with stringified version of
55+ // the config, and then it calls the transformer with the proper object
56+ serializedCcs . jestConfig . value = jestConfig
57+ this . _transformCfgStr = serializedCcs . transformerCfgStr
58+ configSet = serializedCcs . configSet
59+ } else {
60+ // create the new record in the index
61+ this . logger . info ( 'no matching config-set found, creating a new one' )
62+
63+ configSet = new ConfigSet ( jestConfig )
64+ this . _transformCfgStr = new JsonableValue ( {
65+ digest : configSet . tsJestDigest ,
66+ babel : configSet . babelConfig ,
67+ ...jestConfig ,
68+ tsconfig : {
69+ options : configSet . parsedTsConfig . options ,
70+ raw : configSet . parsedTsConfig . raw ,
71+ } ,
72+ } ) . serialized
73+ TsJestTransformer . _cachedConfigSets . push ( {
74+ jestConfig : new JsonableValue ( jestConfig ) ,
75+ configSet,
76+ transformerCfgStr : this . _transformCfgStr ,
77+ } )
78+ }
79+ }
80+
81+ return configSet
82+ }
83+
84+ /**
85+ * @public
86+ */
3687 process (
3788 input : string ,
3889 filePath : Config . Path ,
@@ -43,9 +94,10 @@ export class TsJestTransformer implements Transformer {
4394
4495 let result : string | TransformedSource
4596 const source : string = input
46- const { hooks } = this . _configSet
47- const shouldStringifyContent = this . _configSet . shouldStringifyContent ( filePath )
48- const babelJest = shouldStringifyContent ? undefined : this . _configSet . babelJestTransformer
97+ const configs = this . configsFor ( jestConfig )
98+ const { hooks } = configs
99+ const shouldStringifyContent = configs . shouldStringifyContent ( filePath )
100+ const babelJest = shouldStringifyContent ? undefined : configs . babelJestTransformer
49101 const isDefinitionFile = filePath . endsWith ( DECLARATION_TYPE_EXT )
50102 const isJsFile = JS_JSX_REGEX . test ( filePath )
51103 const isTsFile = ! isDefinitionFile && TS_TSX_REGEX . test ( filePath )
@@ -55,15 +107,15 @@ export class TsJestTransformer implements Transformer {
55107 } else if ( isDefinitionFile ) {
56108 // do not try to compile declaration files
57109 result = ''
58- } else if ( ! this . _configSet . parsedTsConfig . options . allowJs && isJsFile ) {
110+ } else if ( ! configs . parsedTsConfig . options . allowJs && isJsFile ) {
59111 // we've got a '.js' but the compiler option `allowJs` is not set or set to false
60112 this . logger . warn ( { fileName : filePath } , interpolate ( Errors . GotJsFileButAllowJsFalse , { path : filePath } ) )
61113
62114 result = source
63115 } else if ( isJsFile || isTsFile ) {
64116 // transpile TS code (source maps are included)
65117 /* istanbul ignore if */
66- result = this . _configSet . tsCompiler . compile ( source , filePath )
118+ result = configs . tsCompiler . compile ( source , filePath )
67119 } else {
68120 // we should not get called for files with other extension than js[x], ts[x] and d.ts,
69121 // TypeScript will bail if we try to compile, and if it was to call babel, users can
@@ -99,66 +151,32 @@ export class TsJestTransformer implements Transformer {
99151 * Jest uses this to cache the compiled version of a file
100152 *
101153 * @see https://github.com/facebook/jest/blob/v23.5.0/packages/jest-runtime/src/script_transformer.js#L61-L90
154+ *
155+ * @public
102156 */
103157 getCacheKey (
104158 fileContent : string ,
105159 filePath : string ,
106160 _jestConfigStr : string ,
107161 transformOptions : CacheKeyOptions ,
108162 ) : string {
109- this . createOrResolveTransformerCfg ( transformOptions . config )
163+ const configs = this . configsFor ( transformOptions . config )
110164
111165 this . logger . debug ( { fileName : filePath , transformOptions } , 'computing cache key for' , filePath )
112166
113- return createCacheKey ( ) ( fileContent , filePath , this . _transformCfgStr , {
114- config : transformOptions . config ,
115- instrument : false ,
116- } )
117- }
118-
119- /**
120- * Users can override this method and provide their own config class
121- */
122- protected createOrResolveTransformerCfg ( jestConfig : Config . ProjectConfig ) : void {
123- const ccs : CachedConfigSet | undefined = TsJestTransformer . _cachedConfigSets . find (
124- ( cs ) => cs . jestConfig . value === jestConfig ,
167+ // we do not instrument, ensure it is false all the time
168+ const { instrument = false , rootDir = configs . rootDir } = transformOptions
169+
170+ return sha1 (
171+ this . _transformCfgStr ,
172+ '\x00' ,
173+ rootDir ,
174+ '\x00' ,
175+ `instrument:${ instrument ? 'on' : 'off' } ` ,
176+ '\x00' ,
177+ fileContent ,
178+ '\x00' ,
179+ filePath ,
125180 )
126- if ( ccs ) {
127- this . _transformCfgStr = ccs . transformerCfgStr
128- this . _configSet = ccs . configSet
129- } else {
130- // try to look-it up by stringified version
131- const serializedJestCfg = stringify ( jestConfig )
132- const serializedCcs = TsJestTransformer . _cachedConfigSets . find (
133- ( cs ) => cs . jestConfig . serialized === serializedJestCfg ,
134- )
135- if ( serializedCcs ) {
136- // update the object so that we can find it later
137- // this happens because jest first calls getCacheKey with stringified version of
138- // the config, and then it calls the transformer with the proper object
139- serializedCcs . jestConfig . value = jestConfig
140- this . _transformCfgStr = serializedCcs . transformerCfgStr
141- this . _configSet = serializedCcs . configSet
142- } else {
143- // create the new record in the index
144- this . logger . info ( 'no matching config-set found, creating a new one' )
145-
146- this . _configSet = new ConfigSet ( jestConfig )
147- this . _transformCfgStr = new JsonableValue ( {
148- digest : this . _configSet . tsJestDigest ,
149- babel : this . _configSet . babelConfig ,
150- ...jestConfig ,
151- tsconfig : {
152- options : this . _configSet . parsedTsConfig . options ,
153- raw : this . _configSet . parsedTsConfig . raw ,
154- } ,
155- } ) . serialized
156- TsJestTransformer . _cachedConfigSets . push ( {
157- jestConfig : new JsonableValue ( jestConfig ) ,
158- configSet : this . _configSet ,
159- transformerCfgStr : this . _transformCfgStr ,
160- } )
161- }
162- }
163181 }
164182}
0 commit comments